s3-spoolss: make sure members of "BUILTIN\Print Operators" can open printers
[samba.git] / source3 / rpc_server / 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 "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/cli_spoolss.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "librpc/gen_ndr/messaging.h"
37 #include "../libcli/security/security.h"
38 #include "librpc/gen_ndr/ndr_security.h"
39 #include "registry.h"
40 #include "registry/reg_objects.h"
41 #include "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45
46 /* macros stolen from s4 spoolss server */
47 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
48         ((info)?ndr_size_##fn(info, level, 0):0)
49
50 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
51         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
52
53 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
54         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
55
56 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
57
58 #undef DBGC_CLASS
59 #define DBGC_CLASS DBGC_RPC_SRV
60
61 #ifndef MAX_OPEN_PRINTER_EXS
62 #define MAX_OPEN_PRINTER_EXS 50
63 #endif
64
65 struct notify_back_channel;
66
67 /* structure to store the printer handles */
68 /* and a reference to what it's pointing to */
69 /* and the notify info asked about */
70 /* that's the central struct */
71 struct printer_handle {
72         struct printer_handle *prev, *next;
73         bool document_started;
74         bool page_started;
75         uint32 jobid; /* jobid in printing backend */
76         int printer_type;
77         const char *servername;
78         fstring sharename;
79         uint32 type;
80         uint32 access_granted;
81         struct {
82                 uint32 flags;
83                 uint32 options;
84                 fstring localmachine;
85                 uint32 printerlocal;
86                 struct spoolss_NotifyOption *option;
87                 struct policy_handle cli_hnd;
88                 struct notify_back_channel *cli_chan;
89                 uint32 change;
90                 /* are we in a FindNextPrinterChangeNotify() call? */
91                 bool fnpcn;
92                 struct messaging_context *msg_ctx;
93         } notify;
94         struct {
95                 fstring machine;
96                 fstring user;
97         } client;
98
99         /* devmode sent in the OpenPrinter() call */
100         struct spoolss_DeviceMode *devmode;
101
102         /* TODO cache the printer info2 structure */
103         struct spoolss_PrinterInfo2 *info2;
104
105 };
106
107 static struct printer_handle *printers_list;
108
109 struct printer_session_counter {
110         struct printer_session_counter *next;
111         struct printer_session_counter *prev;
112
113         int snum;
114         uint32_t counter;
115 };
116
117 static struct printer_session_counter *counter_list;
118
119 struct notify_back_channel {
120         struct notify_back_channel *prev, *next;
121
122         /* associated client */
123         struct sockaddr_storage client_address;
124
125         /* print notify back-channel pipe handle*/
126         struct rpc_pipe_client *cli_pipe;
127         uint32_t active_connections;
128 };
129
130 static struct notify_back_channel *back_channels;
131
132 /* Map generic permissions to printer object specific permissions */
133
134 const struct standard_mapping printer_std_mapping = {
135         PRINTER_READ,
136         PRINTER_WRITE,
137         PRINTER_EXECUTE,
138         PRINTER_ALL_ACCESS
139 };
140
141 /* Map generic permissions to print server object specific permissions */
142
143 const struct standard_mapping printserver_std_mapping = {
144         SERVER_READ,
145         SERVER_WRITE,
146         SERVER_EXECUTE,
147         SERVER_ALL_ACCESS
148 };
149
150 /* API table for Xcv Monitor functions */
151
152 struct xcv_api_table {
153         const char *name;
154         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
155 };
156
157 static void prune_printername_cache(void);
158
159 /********************************************************************
160  * Canonicalize servername.
161  ********************************************************************/
162
163 static const char *canon_servername(const char *servername)
164 {
165         const char *pservername = servername;
166         while (*pservername == '\\') {
167                 pservername++;
168         }
169         return pservername;
170 }
171
172 /* translate between internal status numbers and NT status numbers */
173 static int nt_printj_status(int v)
174 {
175         switch (v) {
176         case LPQ_QUEUED:
177                 return 0;
178         case LPQ_PAUSED:
179                 return JOB_STATUS_PAUSED;
180         case LPQ_SPOOLING:
181                 return JOB_STATUS_SPOOLING;
182         case LPQ_PRINTING:
183                 return JOB_STATUS_PRINTING;
184         case LPQ_ERROR:
185                 return JOB_STATUS_ERROR;
186         case LPQ_DELETING:
187                 return JOB_STATUS_DELETING;
188         case LPQ_OFFLINE:
189                 return JOB_STATUS_OFFLINE;
190         case LPQ_PAPEROUT:
191                 return JOB_STATUS_PAPEROUT;
192         case LPQ_PRINTED:
193                 return JOB_STATUS_PRINTED;
194         case LPQ_DELETED:
195                 return JOB_STATUS_DELETED;
196         case LPQ_BLOCKED:
197                 return JOB_STATUS_BLOCKED_DEVQ;
198         case LPQ_USER_INTERVENTION:
199                 return JOB_STATUS_USER_INTERVENTION;
200         }
201         return 0;
202 }
203
204 static int nt_printq_status(int v)
205 {
206         switch (v) {
207         case LPQ_PAUSED:
208                 return PRINTER_STATUS_PAUSED;
209         case LPQ_QUEUED:
210         case LPQ_SPOOLING:
211         case LPQ_PRINTING:
212                 return 0;
213         }
214         return 0;
215 }
216
217 /***************************************************************************
218  Disconnect from the client
219 ****************************************************************************/
220
221 static void srv_spoolss_replycloseprinter(int snum,
222                                           struct printer_handle *prn_hnd)
223 {
224         WERROR result;
225         NTSTATUS status;
226
227         /*
228          * Tell the specific printing tdb we no longer want messages for this printer
229          * by deregistering our PID.
230          */
231
232         if (!print_notify_deregister_pid(snum)) {
233                 DEBUG(0, ("Failed to register our pid for printer %s\n",
234                           lp_const_servicename(snum)));
235         }
236
237         /* weird if the test succeeds !!! */
238         if (prn_hnd->notify.cli_chan == NULL ||
239             prn_hnd->notify.cli_chan->active_connections == 0) {
240                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
241                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
242                 TALLOC_FREE(prn_hnd->notify.cli_chan);
243                 return;
244         }
245
246         status = rpccli_spoolss_ReplyClosePrinter(
247                                         prn_hnd->notify.cli_chan->cli_pipe,
248                                         talloc_tos(),
249                                         &prn_hnd->notify.cli_hnd,
250                                         &result);
251         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
252                 DEBUG(0, ("reply_close_printer failed [%s].\n",
253                           win_errstr(result)));
254         }
255
256         /* if it's the last connection, deconnect the IPC$ share */
257         if (prn_hnd->notify.cli_chan->active_connections == 1) {
258
259                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
260                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
261                 TALLOC_FREE(prn_hnd->notify.cli_chan);
262
263                 if (prn_hnd->notify.msg_ctx != NULL) {
264                         messaging_deregister(prn_hnd->notify.msg_ctx,
265                                              MSG_PRINTER_NOTIFY2, NULL);
266
267                         /*
268                          * Tell the serverid.tdb we're no longer
269                          * interested in printer notify messages.
270                          */
271
272                         serverid_register_msg_flags(
273                                 messaging_server_id(prn_hnd->notify.msg_ctx),
274                                 false, FLAG_MSG_PRINT_NOTIFY);
275                 }
276         }
277
278         if (prn_hnd->notify.cli_chan) {
279                 prn_hnd->notify.cli_chan->active_connections--;
280         }
281 }
282
283 /****************************************************************************
284  Functions to free a printer entry datastruct.
285 ****************************************************************************/
286
287 static int printer_entry_destructor(struct printer_handle *Printer)
288 {
289         if (Printer->notify.cli_chan != NULL &&
290             Printer->notify.cli_chan->active_connections > 0) {
291                 int snum = -1;
292
293                 switch(Printer->printer_type) {
294                 case SPLHND_SERVER:
295                         srv_spoolss_replycloseprinter(snum, Printer);
296                         break;
297
298                 case SPLHND_PRINTER:
299                         snum = print_queue_snum(Printer->sharename);
300                         if (snum != -1) {
301                                 srv_spoolss_replycloseprinter(snum, Printer);
302                         }
303                         break;
304                 default:
305                         break;
306                 }
307         }
308
309         Printer->notify.flags=0;
310         Printer->notify.options=0;
311         Printer->notify.localmachine[0]='\0';
312         Printer->notify.printerlocal=0;
313         TALLOC_FREE(Printer->notify.option);
314         TALLOC_FREE(Printer->devmode);
315
316         /* Remove from the internal list. */
317         DLIST_REMOVE(printers_list, Printer);
318         return 0;
319 }
320
321 /****************************************************************************
322   find printer index by handle
323 ****************************************************************************/
324
325 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
326                                                         struct policy_handle *hnd)
327 {
328         struct printer_handle *find_printer = NULL;
329
330         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
331                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
332                 return NULL;
333         }
334
335         return find_printer;
336 }
337
338 /****************************************************************************
339  Close printer index by handle.
340 ****************************************************************************/
341
342 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
343 {
344         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
345
346         if (!Printer) {
347                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
348                         OUR_HANDLE(hnd)));
349                 return false;
350         }
351
352         close_policy_hnd(p, hnd);
353
354         return true;
355 }
356
357 /****************************************************************************
358  Delete a printer given a handle.
359 ****************************************************************************/
360
361 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
362                                   const char *sharename,
363                                   struct messaging_context *msg_ctx)
364 {
365         char *cmd = lp_deleteprinter_cmd();
366         char *command = NULL;
367         int ret;
368         bool is_print_op = false;
369
370         /* can't fail if we don't try */
371
372         if ( !*cmd )
373                 return WERR_OK;
374
375         command = talloc_asprintf(ctx,
376                         "%s \"%s\"",
377                         cmd, sharename);
378         if (!command) {
379                 return WERR_NOMEM;
380         }
381         if ( token )
382                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
383
384         DEBUG(10,("Running [%s]\n", command));
385
386         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
387
388         if ( is_print_op )
389                 become_root();
390
391         if ( (ret = smbrun(command, NULL)) == 0 ) {
392                 /* Tell everyone we updated smb.conf. */
393                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
394         }
395
396         if ( is_print_op )
397                 unbecome_root();
398
399         /********** END SePrintOperatorPrivlege BLOCK **********/
400
401         DEBUGADD(10,("returned [%d]\n", ret));
402
403         TALLOC_FREE(command);
404
405         if (ret != 0)
406                 return WERR_BADFID; /* What to return here? */
407
408         /* go ahead and re-read the services immediately */
409         become_root();
410         reload_services(msg_ctx, -1, false);
411         unbecome_root();
412
413         if ( lp_servicenumber( sharename ) >= 0 )
414                 return WERR_ACCESS_DENIED;
415
416         return WERR_OK;
417 }
418
419 /****************************************************************************
420  Delete a printer given a handle.
421 ****************************************************************************/
422
423 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
424 {
425         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
426         WERROR result;
427
428         if (!Printer) {
429                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
430                         OUR_HANDLE(hnd)));
431                 return WERR_BADFID;
432         }
433
434         /*
435          * It turns out that Windows allows delete printer on a handle
436          * opened by an admin user, then used on a pipe handle created
437          * by an anonymous user..... but they're working on security.... riiight !
438          * JRA.
439          */
440
441         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
442                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
443                 return WERR_ACCESS_DENIED;
444         }
445
446         /* this does not need a become root since the access check has been
447            done on the handle already */
448
449         result = winreg_delete_printer_key(p->mem_ctx,
450                                            get_server_info_system(),
451                                            p->msg_ctx,
452                                            Printer->sharename,
453                                            "");
454         if (!W_ERROR_IS_OK(result)) {
455                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
456                 return WERR_BADFID;
457         }
458
459         result = delete_printer_hook(p->mem_ctx, p->server_info->ptok,
460                                      Printer->sharename, p->msg_ctx);
461         if (!W_ERROR_IS_OK(result)) {
462                 return result;
463         }
464         prune_printername_cache();
465         return WERR_OK;
466 }
467
468 /****************************************************************************
469  Return the snum of a printer corresponding to an handle.
470 ****************************************************************************/
471
472 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
473                              int *number, struct share_params **params)
474 {
475         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
476
477         if (!Printer) {
478                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
479                         OUR_HANDLE(hnd)));
480                 return false;
481         }
482
483         switch (Printer->printer_type) {
484                 case SPLHND_PRINTER:
485                         DEBUG(4,("short name:%s\n", Printer->sharename));
486                         *number = print_queue_snum(Printer->sharename);
487                         return (*number != -1);
488                 case SPLHND_SERVER:
489                         return false;
490                 default:
491                         return false;
492         }
493 }
494
495 /****************************************************************************
496  Set printer handle type.
497  Check if it's \\server or \\server\printer
498 ****************************************************************************/
499
500 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
501 {
502         DEBUG(3,("Setting printer type=%s\n", handlename));
503
504         /* it's a print server */
505         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
506                 DEBUGADD(4,("Printer is a print server\n"));
507                 Printer->printer_type = SPLHND_SERVER;
508         }
509         /* it's a printer (set_printer_hnd_name() will handle port monitors */
510         else {
511                 DEBUGADD(4,("Printer is a printer\n"));
512                 Printer->printer_type = SPLHND_PRINTER;
513         }
514
515         return true;
516 }
517
518 static void prune_printername_cache_fn(const char *key, const char *value,
519                                        time_t timeout, void *private_data)
520 {
521         gencache_del(key);
522 }
523
524 static void prune_printername_cache(void)
525 {
526         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
527 }
528
529 /****************************************************************************
530  Set printer handle name..  Accept names like \\server, \\server\printer,
531  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
532  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
533  XcvDataPort() interface.
534 ****************************************************************************/
535
536 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
537                                    const struct auth_serversupplied_info *server_info,
538                                    struct messaging_context *msg_ctx,
539                                    struct printer_handle *Printer,
540                                    const char *handlename)
541 {
542         int snum;
543         int n_services=lp_numservices();
544         char *aprinter;
545         const char *printername;
546         const char *servername = NULL;
547         fstring sname;
548         bool found = false;
549         struct spoolss_PrinterInfo2 *info2 = NULL;
550         WERROR result;
551         char *p;
552
553         /*
554          * Hopefully nobody names his printers like this. Maybe \ or ,
555          * are illegal in printer names even?
556          */
557         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
558         char *cache_key;
559         char *tmp;
560
561         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
562                 (unsigned long)strlen(handlename)));
563
564         aprinter = CONST_DISCARD(char *, handlename);
565         if ( *handlename == '\\' ) {
566                 servername = canon_servername(handlename);
567                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
568                         *aprinter = '\0';
569                         aprinter++;
570                 }
571                 if (!is_myname_or_ipaddr(servername)) {
572                         return WERR_INVALID_PRINTER_NAME;
573                 }
574                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
575                 if (Printer->servername == NULL) {
576                         return WERR_NOMEM;
577                 }
578         }
579
580         if (Printer->printer_type == SPLHND_SERVER) {
581                 return WERR_OK;
582         }
583
584         if (Printer->printer_type != SPLHND_PRINTER) {
585                 return WERR_INVALID_HANDLE;
586         }
587
588         DEBUGADD(5, ("searching for [%s]\n", aprinter));
589
590         p = strchr(aprinter, ',');
591         if (p != NULL) {
592                 char *p2 = p;
593                 p++;
594                 if (*p == ' ') {
595                         p++;
596                 }
597                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
598                         *p2 = '\0';
599                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
600                         *p2 = '\0';
601                 }
602         }
603
604         if (p) {
605                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
606         }
607
608         /* check for the Port Monitor Interface */
609         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
610                 Printer->printer_type = SPLHND_PORTMON_TCP;
611                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
612                 found = true;
613         }
614         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
615                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
616                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
617                 found = true;
618         }
619
620         /*
621          * With hundreds of printers, the "for" loop iterating all
622          * shares can be quite expensive, as it is done on every
623          * OpenPrinter. The loop maps "aprinter" to "sname", the
624          * result of which we cache in gencache.
625          */
626
627         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
628                                     aprinter);
629         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
630
631                 found = (strcmp(tmp, printer_not_found) != 0);
632                 if (!found) {
633                         DEBUG(4, ("Printer %s not found\n", aprinter));
634                         SAFE_FREE(tmp);
635                         return WERR_INVALID_PRINTER_NAME;
636                 }
637                 fstrcpy(sname, tmp);
638                 SAFE_FREE(tmp);
639         }
640
641         /* Search all sharenames first as this is easier than pulling
642            the printer_info_2 off of disk. Don't use find_service() since
643            that calls out to map_username() */
644
645         /* do another loop to look for printernames */
646         for (snum = 0; !found && snum < n_services; snum++) {
647                 const char *printer = lp_const_servicename(snum);
648
649                 /* no point going on if this is not a printer */
650                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
651                         continue;
652                 }
653
654                 /* ignore [printers] share */
655                 if (strequal(printer, "printers")) {
656                         continue;
657                 }
658
659                 fstrcpy(sname, printer);
660                 if (strequal(aprinter, printer)) {
661                         found = true;
662                         break;
663                 }
664
665                 /* no point looking up the printer object if
666                    we aren't allowing printername != sharename */
667                 if (lp_force_printername(snum)) {
668                         continue;
669                 }
670
671                 result = winreg_get_printer(mem_ctx,
672                                             server_info,
673                                             msg_ctx,
674                                             sname,
675                                             &info2);
676                 if ( !W_ERROR_IS_OK(result) ) {
677                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
678                                  sname, win_errstr(result)));
679                         continue;
680                 }
681
682                 printername = strrchr(info2->printername, '\\');
683                 if (printername == NULL) {
684                         printername = info2->printername;
685                 } else {
686                         printername++;
687                 }
688
689                 if (strequal(printername, aprinter)) {
690                         found = true;
691                         break;
692                 }
693
694                 DEBUGADD(10, ("printername: %s\n", printername));
695
696                 TALLOC_FREE(info2);
697         }
698
699         if ( !found ) {
700                 if (cache_key != NULL) {
701                         gencache_set(cache_key, printer_not_found,
702                                      time(NULL)+300);
703                         TALLOC_FREE(cache_key);
704                 }
705                 DEBUGADD(4,("Printer not found\n"));
706                 return WERR_INVALID_PRINTER_NAME;
707         }
708
709         if (cache_key != NULL) {
710                 gencache_set(cache_key, sname, time(NULL)+300);
711                 TALLOC_FREE(cache_key);
712         }
713
714         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
715
716         fstrcpy(Printer->sharename, sname);
717
718         return WERR_OK;
719 }
720
721 /****************************************************************************
722  Find first available printer slot. creates a printer handle for you.
723  ****************************************************************************/
724
725 static WERROR open_printer_hnd(struct pipes_struct *p,
726                                struct policy_handle *hnd,
727                                const char *name,
728                                uint32_t access_granted)
729 {
730         struct printer_handle *new_printer;
731         WERROR result;
732
733         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
734
735         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
736         if (new_printer == NULL) {
737                 return WERR_NOMEM;
738         }
739         talloc_set_destructor(new_printer, printer_entry_destructor);
740
741         /* This also steals the printer_handle on the policy_handle */
742         if (!create_policy_hnd(p, hnd, new_printer)) {
743                 TALLOC_FREE(new_printer);
744                 return WERR_INVALID_HANDLE;
745         }
746
747         /* Add to the internal list. */
748         DLIST_ADD(printers_list, new_printer);
749
750         new_printer->notify.option=NULL;
751
752         if (!set_printer_hnd_printertype(new_printer, name)) {
753                 close_printer_handle(p, hnd);
754                 return WERR_INVALID_HANDLE;
755         }
756
757         result = set_printer_hnd_name(p->mem_ctx,
758                                       get_server_info_system(),
759                                       p->msg_ctx,
760                                       new_printer, name);
761         if (!W_ERROR_IS_OK(result)) {
762                 close_printer_handle(p, hnd);
763                 return result;
764         }
765
766         new_printer->access_granted = access_granted;
767
768         DEBUG(5, ("%d printer handles active\n",
769                   (int)num_pipe_handles(p)));
770
771         return WERR_OK;
772 }
773
774 /***************************************************************************
775  check to see if the client motify handle is monitoring the notification
776  given by (notify_type, notify_field).
777  **************************************************************************/
778
779 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
780                                       uint16_t notify_field)
781 {
782         return true;
783 }
784
785 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
786                                 uint16_t notify_field)
787 {
788         struct spoolss_NotifyOption *option = p->notify.option;
789         uint32_t i, j;
790
791         /*
792          * Flags should always be zero when the change notify
793          * is registered by the client's spooler.  A user Win32 app
794          * might use the flags though instead of the NOTIFY_OPTION_INFO
795          * --jerry
796          */
797
798         if (!option) {
799                 return false;
800         }
801
802         if (p->notify.flags)
803                 return is_monitoring_event_flags(
804                         p->notify.flags, notify_type, notify_field);
805
806         for (i = 0; i < option->count; i++) {
807
808                 /* Check match for notify_type */
809
810                 if (option->types[i].type != notify_type)
811                         continue;
812
813                 /* Check match for field */
814
815                 for (j = 0; j < option->types[i].count; j++) {
816                         if (option->types[i].fields[j].field == notify_field) {
817                                 return true;
818                         }
819                 }
820         }
821
822         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
823                    p->servername, p->sharename, notify_type, notify_field));
824
825         return false;
826 }
827
828 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
829         _data->data.integer[0] = _integer; \
830         _data->data.integer[1] = 0;
831
832
833 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
834         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
835         if (!_data->data.string.string) {\
836                 _data->data.string.size = 0; \
837         } \
838         _data->data.string.size = strlen_m_term(_p) * 2;
839
840 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
841         _data->data.devmode.devmode = _devmode;
842
843 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
844         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
845         if (!_data->data.sd.sd) { \
846                 _data->data.sd.sd_size = 0; \
847         } \
848         _data->data.sd.sd_size = \
849                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
850
851 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
852                                    struct tm *t,
853                                    const char **pp,
854                                    uint32_t *plen)
855 {
856         struct spoolss_Time st;
857         uint32_t len = 16;
858         char *p;
859
860         if (!init_systemtime(&st, t)) {
861                 return;
862         }
863
864         p = talloc_array(mem_ctx, char, len);
865         if (!p) {
866                 return;
867         }
868
869         /*
870          * Systemtime must be linearized as a set of UINT16's.
871          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
872          */
873
874         SSVAL(p, 0, st.year);
875         SSVAL(p, 2, st.month);
876         SSVAL(p, 4, st.day_of_week);
877         SSVAL(p, 6, st.day);
878         SSVAL(p, 8, st.hour);
879         SSVAL(p, 10, st.minute);
880         SSVAL(p, 12, st.second);
881         SSVAL(p, 14, st.millisecond);
882
883         *pp = p;
884         *plen = len;
885 }
886
887 /* Convert a notification message to a struct spoolss_Notify */
888
889 static void notify_one_value(struct spoolss_notify_msg *msg,
890                              struct spoolss_Notify *data,
891                              TALLOC_CTX *mem_ctx)
892 {
893         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
894 }
895
896 static void notify_string(struct spoolss_notify_msg *msg,
897                           struct spoolss_Notify *data,
898                           TALLOC_CTX *mem_ctx)
899 {
900         /* The length of the message includes the trailing \0 */
901
902         data->data.string.size = msg->len * 2;
903         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
904         if (!data->data.string.string) {
905                 data->data.string.size = 0;
906                 return;
907         }
908 }
909
910 static void notify_system_time(struct spoolss_notify_msg *msg,
911                                struct spoolss_Notify *data,
912                                TALLOC_CTX *mem_ctx)
913 {
914         data->data.string.string = NULL;
915         data->data.string.size = 0;
916
917         if (msg->len != sizeof(time_t)) {
918                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
919                           msg->len));
920                 return;
921         }
922
923         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
924                                &data->data.string.string,
925                                &data->data.string.size);
926 }
927
928 struct notify2_message_table {
929         const char *name;
930         void (*fn)(struct spoolss_notify_msg *msg,
931                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
932 };
933
934 static struct notify2_message_table printer_notify_table[] = {
935         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
936         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
937         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
938         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
939         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
940         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
941         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
942         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
943         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
944         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
945         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
946         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
947         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
948         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
949         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
950         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
951         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
952         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
953         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
954 };
955
956 static struct notify2_message_table job_notify_table[] = {
957         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
958         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
959         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
960         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
961         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
962         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
963         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
964         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
965         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
966         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
967         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
968         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
969         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
970         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
971         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
972         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
973         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
974         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
975         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
976         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
977         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
978         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
979         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
980         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
981 };
982
983
984 /***********************************************************************
985  Allocate talloc context for container object
986  **********************************************************************/
987
988 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
989 {
990         if ( !ctr )
991                 return;
992
993         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
994
995         return;
996 }
997
998 /***********************************************************************
999  release all allocated memory and zero out structure
1000  **********************************************************************/
1001
1002 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1003 {
1004         if ( !ctr )
1005                 return;
1006
1007         if ( ctr->ctx )
1008                 talloc_destroy(ctr->ctx);
1009
1010         ZERO_STRUCTP(ctr);
1011
1012         return;
1013 }
1014
1015 /***********************************************************************
1016  **********************************************************************/
1017
1018 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1019 {
1020         if ( !ctr )
1021                 return NULL;
1022
1023         return ctr->ctx;
1024 }
1025
1026 /***********************************************************************
1027  **********************************************************************/
1028
1029 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1030 {
1031         if ( !ctr || !ctr->msg_groups )
1032                 return NULL;
1033
1034         if ( idx >= ctr->num_groups )
1035                 return NULL;
1036
1037         return &ctr->msg_groups[idx];
1038
1039 }
1040
1041 /***********************************************************************
1042  How many groups of change messages do we have ?
1043  **********************************************************************/
1044
1045 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1046 {
1047         if ( !ctr )
1048                 return 0;
1049
1050         return ctr->num_groups;
1051 }
1052
1053 /***********************************************************************
1054  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1055  **********************************************************************/
1056
1057 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1058 {
1059         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1060         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1061         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1062         int                             i, new_slot;
1063
1064         if ( !ctr || !msg )
1065                 return 0;
1066
1067         /* loop over all groups looking for a matching printer name */
1068
1069         for ( i=0; i<ctr->num_groups; i++ ) {
1070                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1071                         break;
1072         }
1073
1074         /* add a new group? */
1075
1076         if ( i == ctr->num_groups ) {
1077                 ctr->num_groups++;
1078
1079                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1080                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1081                         return 0;
1082                 }
1083                 ctr->msg_groups = groups;
1084
1085                 /* clear the new entry and set the printer name */
1086
1087                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1088                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1089         }
1090
1091         /* add the change messages; 'i' is the correct index now regardless */
1092
1093         msg_grp = &ctr->msg_groups[i];
1094
1095         msg_grp->num_msgs++;
1096
1097         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1098                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1099                 return 0;
1100         }
1101         msg_grp->msgs = msg_list;
1102
1103         new_slot = msg_grp->num_msgs-1;
1104         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1105
1106         /* need to allocate own copy of data */
1107
1108         if ( msg->len != 0 )
1109                 msg_grp->msgs[new_slot].notify.data = (char *)
1110                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1111
1112         return ctr->num_groups;
1113 }
1114
1115 static void construct_info_data(struct spoolss_Notify *info_data,
1116                                 enum spoolss_NotifyType type,
1117                                 uint16_t field, int id);
1118
1119 /***********************************************************************
1120  Send a change notication message on all handles which have a call
1121  back registered
1122  **********************************************************************/
1123
1124 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1125                                   struct printer_handle *prn_hnd,
1126                                   SPOOLSS_NOTIFY_MSG *messages,
1127                                   uint32_t num_msgs,
1128                                   struct spoolss_Notify **_notifies,
1129                                   int *_count)
1130 {
1131         struct spoolss_Notify *notifies;
1132         SPOOLSS_NOTIFY_MSG *msg;
1133         int count = 0;
1134         uint32_t id;
1135         int i;
1136
1137         notifies = talloc_zero_array(mem_ctx,
1138                                      struct spoolss_Notify, num_msgs);
1139         if (!notifies) {
1140                 return ENOMEM;
1141         }
1142
1143         for (i = 0; i < num_msgs; i++) {
1144
1145                 msg = &messages[i];
1146
1147                 /* Are we monitoring this event? */
1148
1149                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1150                         continue;
1151                 }
1152
1153                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1154                            "for printer [%s]\n",
1155                            msg->type, msg->field, prn_hnd->sharename));
1156
1157                 /*
1158                  * if the is a printer notification handle and not a job
1159                  * notification type, then set the id to 0.
1160                  * Otherwise just use what was specified in the message.
1161                  *
1162                  * When registering change notification on a print server
1163                  * handle we always need to send back the id (snum) matching
1164                  * the printer for which the change took place.
1165                  * For change notify registered on a printer handle,
1166                  * this does not matter and the id should be 0.
1167                  *
1168                  * --jerry
1169                  */
1170
1171                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1172                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1173                         id = 0;
1174                 } else {
1175                         id = msg->id;
1176                 }
1177
1178                 /* Convert unix jobid to smb jobid */
1179
1180                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1181                         id = sysjob_to_jobid(msg->id);
1182
1183                         if (id == -1) {
1184                                 DEBUG(3, ("no such unix jobid %d\n",
1185                                           msg->id));
1186                                 continue;
1187                         }
1188                 }
1189
1190                 construct_info_data(&notifies[count],
1191                                     msg->type, msg->field, id);
1192
1193                 switch(msg->type) {
1194                 case PRINTER_NOTIFY_TYPE:
1195                         if (printer_notify_table[msg->field].fn) {
1196                                 printer_notify_table[msg->field].fn(msg,
1197                                                 &notifies[count], mem_ctx);
1198                         }
1199                         break;
1200
1201                 case JOB_NOTIFY_TYPE:
1202                         if (job_notify_table[msg->field].fn) {
1203                                 job_notify_table[msg->field].fn(msg,
1204                                                 &notifies[count], mem_ctx);
1205                         }
1206                         break;
1207
1208                 default:
1209                         DEBUG(5, ("Unknown notification type %d\n",
1210                                   msg->type));
1211                         continue;
1212                 }
1213
1214                 count++;
1215         }
1216
1217         *_notifies = notifies;
1218         *_count = count;
1219
1220         return 0;
1221 }
1222
1223 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1224                                 struct printer_handle *prn_hnd,
1225                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1226 {
1227         struct spoolss_Notify *notifies;
1228         int count = 0;
1229         union spoolss_ReplyPrinterInfo info;
1230         struct spoolss_NotifyInfo info0;
1231         uint32_t reply_result;
1232         NTSTATUS status;
1233         WERROR werr;
1234         int ret;
1235
1236         /* Is there notification on this handle? */
1237         if (prn_hnd->notify.cli_chan == NULL ||
1238             prn_hnd->notify.cli_chan->active_connections == 0) {
1239                 return 0;
1240         }
1241
1242         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1243                    prn_hnd->servername, prn_hnd->sharename));
1244
1245         /* For this printer? Print servers always receive notifications. */
1246         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1247             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1248                 return 0;
1249         }
1250
1251         DEBUG(10,("Our printer\n"));
1252
1253         /* build the array of change notifications */
1254         ret = build_notify2_messages(mem_ctx, prn_hnd,
1255                                      msg_group->msgs,
1256                                      msg_group->num_msgs,
1257                                      &notifies, &count);
1258         if (ret) {
1259                 return ret;
1260         }
1261
1262         info0.version   = 0x2;
1263         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1264         info0.count     = count;
1265         info0.notifies  = notifies;
1266
1267         info.info0 = &info0;
1268
1269         status = rpccli_spoolss_RouterReplyPrinterEx(
1270                                 prn_hnd->notify.cli_chan->cli_pipe,
1271                                 mem_ctx,
1272                                 &prn_hnd->notify.cli_hnd,
1273                                 prn_hnd->notify.change, /* color */
1274                                 prn_hnd->notify.flags,
1275                                 &reply_result,
1276                                 0, /* reply_type, must be 0 */
1277                                 info, &werr);
1278         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1279                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1280                           "failed: %s\n",
1281                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1282                           win_errstr(werr)));
1283         }
1284         switch (reply_result) {
1285         case 0:
1286                 break;
1287         case PRINTER_NOTIFY_INFO_DISCARDED:
1288         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1289         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1290                 break;
1291         default:
1292                 break;
1293         }
1294
1295         return 0;
1296 }
1297
1298 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1299 {
1300         struct printer_handle    *p;
1301         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1302         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1303         int ret;
1304
1305         if ( !msg_group ) {
1306                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1307                 return;
1308         }
1309
1310         if (!msg_group->msgs) {
1311                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1312                 return;
1313         }
1314
1315         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1316
1317         /* loop over all printers */
1318
1319         for (p = printers_list; p; p = p->next) {
1320                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1321                 if (ret) {
1322                         goto done;
1323                 }
1324         }
1325
1326 done:
1327         DEBUG(8,("send_notify2_changes: Exit...\n"));
1328         return;
1329 }
1330
1331 /***********************************************************************
1332  **********************************************************************/
1333
1334 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1335 {
1336
1337         uint32_t tv_sec, tv_usec;
1338         size_t offset = 0;
1339
1340         /* Unpack message */
1341
1342         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1343                              msg->printer);
1344
1345         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1346                                 &tv_sec, &tv_usec,
1347                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1348
1349         if (msg->len == 0)
1350                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1351                            &msg->notify.value[0], &msg->notify.value[1]);
1352         else
1353                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1354                            &msg->len, &msg->notify.data);
1355
1356         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1357                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1358
1359         tv->tv_sec = tv_sec;
1360         tv->tv_usec = tv_usec;
1361
1362         if (msg->len == 0)
1363                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1364                           msg->notify.value[1]));
1365         else
1366                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1367
1368         return true;
1369 }
1370
1371 /********************************************************************
1372  Receive a notify2 message list
1373  ********************************************************************/
1374
1375 static void receive_notify2_message_list(struct messaging_context *msg,
1376                                          void *private_data,
1377                                          uint32_t msg_type,
1378                                          struct server_id server_id,
1379                                          DATA_BLOB *data)
1380 {
1381         size_t                  msg_count, i;
1382         char                    *buf = (char *)data->data;
1383         char                    *msg_ptr;
1384         size_t                  msg_len;
1385         SPOOLSS_NOTIFY_MSG      notify;
1386         SPOOLSS_NOTIFY_MSG_CTR  messages;
1387         int                     num_groups;
1388
1389         if (data->length < 4) {
1390                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1391                 return;
1392         }
1393
1394         msg_count = IVAL(buf, 0);
1395         msg_ptr = buf + 4;
1396
1397         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1398
1399         if (msg_count == 0) {
1400                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1401                 return;
1402         }
1403
1404         /* initialize the container */
1405
1406         ZERO_STRUCT( messages );
1407         notify_msg_ctr_init( &messages );
1408
1409         /*
1410          * build message groups for each printer identified
1411          * in a change_notify msg.  Remember that a PCN message
1412          * includes the handle returned for the srv_spoolss_replyopenprinter()
1413          * call.  Therefore messages are grouped according to printer handle.
1414          */
1415
1416         for ( i=0; i<msg_count; i++ ) {
1417                 struct timeval msg_tv;
1418
1419                 if (msg_ptr + 4 - buf > data->length) {
1420                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1421                         return;
1422                 }
1423
1424                 msg_len = IVAL(msg_ptr,0);
1425                 msg_ptr += 4;
1426
1427                 if (msg_ptr + msg_len - buf > data->length) {
1428                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1429                         return;
1430                 }
1431
1432                 /* unpack messages */
1433
1434                 ZERO_STRUCT( notify );
1435                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1436                 msg_ptr += msg_len;
1437
1438                 /* add to correct list in container */
1439
1440                 notify_msg_ctr_addmsg( &messages, &notify );
1441
1442                 /* free memory that might have been allocated by notify2_unpack_msg() */
1443
1444                 if ( notify.len != 0 )
1445                         SAFE_FREE( notify.notify.data );
1446         }
1447
1448         /* process each group of messages */
1449
1450         num_groups = notify_msg_ctr_numgroups( &messages );
1451         for ( i=0; i<num_groups; i++ )
1452                 send_notify2_changes( &messages, i );
1453
1454
1455         /* cleanup */
1456
1457         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1458                 (uint32_t)msg_count ));
1459
1460         notify_msg_ctr_destroy( &messages );
1461
1462         return;
1463 }
1464
1465 /********************************************************************
1466  Send a message to ourself about new driver being installed
1467  so we can upgrade the information for each printer bound to this
1468  driver
1469  ********************************************************************/
1470
1471 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1472                                             struct messaging_context *msg_ctx)
1473 {
1474         int len = strlen(drivername);
1475
1476         if (!len)
1477                 return false;
1478
1479         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1480                 drivername));
1481
1482         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1483                            MSG_PRINTER_DRVUPGRADE,
1484                            (uint8_t *)drivername, len+1);
1485
1486         return true;
1487 }
1488
1489 void srv_spoolss_cleanup(void)
1490 {
1491         struct printer_session_counter *session_counter;
1492
1493         for (session_counter = counter_list;
1494              session_counter != NULL;
1495              session_counter = counter_list) {
1496                 DLIST_REMOVE(counter_list, session_counter);
1497                 TALLOC_FREE(session_counter);
1498         }
1499 }
1500
1501 /**********************************************************************
1502  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1503  over all printers, upgrading ones as necessary
1504  **********************************************************************/
1505
1506 void do_drv_upgrade_printer(struct messaging_context *msg,
1507                             void *private_data,
1508                             uint32_t msg_type,
1509                             struct server_id server_id,
1510                             DATA_BLOB *data)
1511 {
1512         TALLOC_CTX *tmp_ctx;
1513         struct auth_serversupplied_info *server_info = NULL;
1514         struct spoolss_PrinterInfo2 *pinfo2;
1515         NTSTATUS status;
1516         WERROR result;
1517         const char *drivername;
1518         int snum;
1519         int n_services = lp_numservices();
1520
1521         tmp_ctx = talloc_new(NULL);
1522         if (!tmp_ctx) return;
1523
1524         status = make_server_info_system(tmp_ctx, &server_info);
1525         if (!NT_STATUS_IS_OK(status)) {
1526                 DEBUG(0, ("do_drv_upgrade_printer: "
1527                           "Could not create system server_info\n"));
1528                 goto done;
1529         }
1530
1531         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1532         if (!drivername) {
1533                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1534                 goto done;
1535         }
1536
1537         DEBUG(10, ("do_drv_upgrade_printer: "
1538                    "Got message for new driver [%s]\n", drivername));
1539
1540         /* Iterate the printer list */
1541
1542         for (snum = 0; snum < n_services; snum++) {
1543                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1544                         continue;
1545                 }
1546
1547                 /* ignore [printers] share */
1548                 if (strequal(lp_const_servicename(snum), "printers")) {
1549                         continue;
1550                 }
1551
1552                 result = winreg_get_printer(tmp_ctx, server_info, msg,
1553                                             lp_const_servicename(snum),
1554                                             &pinfo2);
1555
1556                 if (!W_ERROR_IS_OK(result)) {
1557                         continue;
1558                 }
1559
1560                 if (!pinfo2->drivername) {
1561                         continue;
1562                 }
1563
1564                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1565                         continue;
1566                 }
1567
1568                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1569
1570                 /* all we care about currently is the change_id */
1571                 result = winreg_printer_update_changeid(tmp_ctx,
1572                                                         server_info,
1573                                                         msg,
1574                                                         pinfo2->printername);
1575
1576                 if (!W_ERROR_IS_OK(result)) {
1577                         DEBUG(3, ("do_drv_upgrade_printer: "
1578                                   "Failed to update changeid [%s]\n",
1579                                   win_errstr(result)));
1580                 }
1581         }
1582
1583         /* all done */
1584 done:
1585         talloc_free(tmp_ctx);
1586 }
1587
1588 /********************************************************************
1589  Update the cache for all printq's with a registered client
1590  connection
1591  ********************************************************************/
1592
1593 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1594 {
1595         struct printer_handle *printer = printers_list;
1596         int snum;
1597
1598         /* loop through all printers and update the cache where
1599            a client is connected */
1600         while (printer) {
1601                 if ((printer->printer_type == SPLHND_PRINTER) &&
1602                     ((printer->notify.cli_chan != NULL) &&
1603                      (printer->notify.cli_chan->active_connections > 0))) {
1604                         snum = print_queue_snum(printer->sharename);
1605                         print_queue_status(msg_ctx, snum, NULL, NULL);
1606                 }
1607
1608                 printer = printer->next;
1609         }
1610
1611         return;
1612 }
1613
1614 /****************************************************************
1615  _spoolss_OpenPrinter
1616 ****************************************************************/
1617
1618 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1619                             struct spoolss_OpenPrinter *r)
1620 {
1621         struct spoolss_OpenPrinterEx e;
1622         WERROR werr;
1623
1624         ZERO_STRUCT(e.in.userlevel);
1625
1626         e.in.printername        = r->in.printername;
1627         e.in.datatype           = r->in.datatype;
1628         e.in.devmode_ctr        = r->in.devmode_ctr;
1629         e.in.access_mask        = r->in.access_mask;
1630         e.in.level              = 0;
1631
1632         e.out.handle            = r->out.handle;
1633
1634         werr = _spoolss_OpenPrinterEx(p, &e);
1635
1636         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1637                 /* OpenPrinterEx returns this for a bad
1638                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1639                  * instead.
1640                  */
1641                 werr = WERR_INVALID_PRINTER_NAME;
1642         }
1643
1644         return werr;
1645 }
1646
1647 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1648                               struct spoolss_DeviceMode *orig,
1649                               struct spoolss_DeviceMode **dest)
1650 {
1651         struct spoolss_DeviceMode *dm;
1652
1653         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1654         if (!dm) {
1655                 return WERR_NOMEM;
1656         }
1657
1658         /* copy all values, then duplicate strings and structs */
1659         *dm = *orig;
1660
1661         dm->devicename = talloc_strdup(dm, orig->devicename);
1662         if (!dm->devicename) {
1663                 return WERR_NOMEM;
1664         }
1665         dm->formname = talloc_strdup(dm, orig->formname);
1666         if (!dm->formname) {
1667                 return WERR_NOMEM;
1668         }
1669         if (orig->driverextra_data.data) {
1670                 dm->driverextra_data.data =
1671                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1672                                         orig->driverextra_data.length);
1673                 if (!dm->driverextra_data.data) {
1674                         return WERR_NOMEM;
1675                 }
1676         }
1677
1678         *dest = dm;
1679         return WERR_OK;
1680 }
1681
1682 /****************************************************************
1683  _spoolss_OpenPrinterEx
1684 ****************************************************************/
1685
1686 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1687                               struct spoolss_OpenPrinterEx *r)
1688 {
1689         int snum;
1690         struct printer_handle *Printer=NULL;
1691         WERROR result;
1692
1693         if (!r->in.printername) {
1694                 return WERR_INVALID_PARAM;
1695         }
1696
1697         if (r->in.level < 0 || r->in.level > 3) {
1698                 return WERR_INVALID_PARAM;
1699         }
1700         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1701             (r->in.level == 2 && !r->in.userlevel.level2) ||
1702             (r->in.level == 3 && !r->in.userlevel.level3)) {
1703                 return WERR_INVALID_PARAM;
1704         }
1705
1706         /* some sanity check because you can open a printer or a print server */
1707         /* aka: \\server\printer or \\server */
1708
1709         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1710
1711         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1712         if (!W_ERROR_IS_OK(result)) {
1713                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1714                         "for printer %s\n", r->in.printername));
1715                 ZERO_STRUCTP(r->out.handle);
1716                 return result;
1717         }
1718
1719         Printer = find_printer_index_by_hnd(p, r->out.handle);
1720         if ( !Printer ) {
1721                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1722                         "handle we created for printer %s\n", r->in.printername));
1723                 close_printer_handle(p, r->out.handle);
1724                 ZERO_STRUCTP(r->out.handle);
1725                 return WERR_INVALID_PARAM;
1726         }
1727
1728         /*
1729          * First case: the user is opening the print server:
1730          *
1731          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1732          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1733          *
1734          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1735          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1736          * or if the user is listed in the smb.conf printer admin parameter.
1737          *
1738          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1739          * client view printer folder, but does not show the MSAPW.
1740          *
1741          * Note: this test needs code to check access rights here too. Jeremy
1742          * could you look at this?
1743          *
1744          * Second case: the user is opening a printer:
1745          * NT doesn't let us connect to a printer if the connecting user
1746          * doesn't have print permission.
1747          *
1748          * Third case: user is opening a Port Monitor
1749          * access checks same as opening a handle to the print server.
1750          */
1751
1752         switch (Printer->printer_type )
1753         {
1754         case SPLHND_SERVER:
1755         case SPLHND_PORTMON_TCP:
1756         case SPLHND_PORTMON_LOCAL:
1757                 /* Printserver handles use global struct... */
1758
1759                 snum = -1;
1760
1761                 /* Map standard access rights to object specific access rights */
1762
1763                 se_map_standard(&r->in.access_mask,
1764                                 &printserver_std_mapping);
1765
1766                 /* Deny any object specific bits that don't apply to print
1767                    servers (i.e printer and job specific bits) */
1768
1769                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1770
1771                 if (r->in.access_mask &
1772                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1773                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1774                         close_printer_handle(p, r->out.handle);
1775                         ZERO_STRUCTP(r->out.handle);
1776                         return WERR_ACCESS_DENIED;
1777                 }
1778
1779                 /* Allow admin access */
1780
1781                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1782                 {
1783                         if (!lp_ms_add_printer_wizard()) {
1784                                 close_printer_handle(p, r->out.handle);
1785                                 ZERO_STRUCTP(r->out.handle);
1786                                 return WERR_ACCESS_DENIED;
1787                         }
1788
1789                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1790                            and not a printer admin, then fail */
1791
1792                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1793                             !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
1794                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->server_info->ptok) &&
1795                             !token_contains_name_in_list(
1796                                     uidtoname(p->server_info->utok.uid),
1797                                     p->server_info->info3->base.domain.string,
1798                                     NULL,
1799                                     p->server_info->ptok,
1800                                     lp_printer_admin(snum))) {
1801                                 close_printer_handle(p, r->out.handle);
1802                                 ZERO_STRUCTP(r->out.handle);
1803                                 DEBUG(3,("access DENIED as user is not root, "
1804                                         "has no printoperator privilege, "
1805                                         "not a member of the printoperater builtin group and "
1806                                         "is not in printer admin list"));
1807                                 return WERR_ACCESS_DENIED;
1808                         }
1809
1810                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1811                 }
1812                 else
1813                 {
1814                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1815                 }
1816
1817                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1818                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1819
1820                 /* We fall through to return WERR_OK */
1821                 break;
1822
1823         case SPLHND_PRINTER:
1824                 /* NT doesn't let us connect to a printer if the connecting user
1825                    doesn't have print permission.  */
1826
1827                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1828                         close_printer_handle(p, r->out.handle);
1829                         ZERO_STRUCTP(r->out.handle);
1830                         return WERR_BADFID;
1831                 }
1832
1833                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1834                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1835                 }
1836
1837                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1838
1839                 /* map an empty access mask to the minimum access mask */
1840                 if (r->in.access_mask == 0x0)
1841                         r->in.access_mask = PRINTER_ACCESS_USE;
1842
1843                 /*
1844                  * If we are not serving the printer driver for this printer,
1845                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1846                  * will keep NT clients happy  --jerry
1847                  */
1848
1849                 if (lp_use_client_driver(snum)
1850                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1851                 {
1852                         r->in.access_mask = PRINTER_ACCESS_USE;
1853                 }
1854
1855                 /* check smb.conf parameters and the the sec_desc */
1856
1857                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1858                                   p->client_id->name, p->client_id->addr)) {
1859                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1860                         ZERO_STRUCTP(r->out.handle);
1861                         return WERR_ACCESS_DENIED;
1862                 }
1863
1864                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1865                                    p->server_info->ptok, snum) ||
1866                     !print_access_check(p->server_info,
1867                                         p->msg_ctx,
1868                                         snum,
1869                                         r->in.access_mask)) {
1870                         DEBUG(3, ("access DENIED for printer open\n"));
1871                         close_printer_handle(p, r->out.handle);
1872                         ZERO_STRUCTP(r->out.handle);
1873                         return WERR_ACCESS_DENIED;
1874                 }
1875
1876                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1877                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1878                         close_printer_handle(p, r->out.handle);
1879                         ZERO_STRUCTP(r->out.handle);
1880                         return WERR_ACCESS_DENIED;
1881                 }
1882
1883                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1884                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1885                 else
1886                         r->in.access_mask = PRINTER_ACCESS_USE;
1887
1888                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1889                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1890
1891                 winreg_create_printer(p->mem_ctx,
1892                                       get_server_info_system(),
1893                                       p->msg_ctx,
1894                                       lp_const_servicename(snum));
1895
1896                 break;
1897
1898         default:
1899                 /* sanity check to prevent programmer error */
1900                 ZERO_STRUCTP(r->out.handle);
1901                 return WERR_BADFID;
1902         }
1903
1904         Printer->access_granted = r->in.access_mask;
1905
1906         /*
1907          * If the client sent a devmode in the OpenPrinter() call, then
1908          * save it here in case we get a job submission on this handle
1909          */
1910
1911          if ((Printer->printer_type != SPLHND_SERVER) &&
1912              r->in.devmode_ctr.devmode) {
1913                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1914                                 &Printer->devmode);
1915          }
1916
1917 #if 0   /* JERRY -- I'm doubtful this is really effective */
1918         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1919            optimization in Windows 2000 clients  --jerry */
1920
1921         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1922                 && (RA_WIN2K == get_remote_arch()) )
1923         {
1924                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1925                 sys_usleep( 500000 );
1926         }
1927 #endif
1928
1929         return WERR_OK;
1930 }
1931
1932 /****************************************************************
1933  _spoolss_ClosePrinter
1934 ****************************************************************/
1935
1936 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1937                              struct spoolss_ClosePrinter *r)
1938 {
1939         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1940
1941         if (Printer && Printer->document_started) {
1942                 struct spoolss_EndDocPrinter e;
1943
1944                 e.in.handle = r->in.handle;
1945
1946                 _spoolss_EndDocPrinter(p, &e);
1947         }
1948
1949         if (!close_printer_handle(p, r->in.handle))
1950                 return WERR_BADFID;
1951
1952         /* clear the returned printer handle.  Observed behavior
1953            from Win2k server.  Don't think this really matters.
1954            Previous code just copied the value of the closed
1955            handle.    --jerry */
1956
1957         ZERO_STRUCTP(r->out.handle);
1958
1959         return WERR_OK;
1960 }
1961
1962 /****************************************************************
1963  _spoolss_DeletePrinter
1964 ****************************************************************/
1965
1966 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1967                               struct spoolss_DeletePrinter *r)
1968 {
1969         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1970         WERROR result;
1971         int snum;
1972
1973         if (Printer && Printer->document_started) {
1974                 struct spoolss_EndDocPrinter e;
1975
1976                 e.in.handle = r->in.handle;
1977
1978                 _spoolss_EndDocPrinter(p, &e);
1979         }
1980
1981         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1982                 winreg_delete_printer_key(p->mem_ctx,
1983                                           get_server_info_system(),
1984                                           p->msg_ctx,
1985                                           lp_const_servicename(snum),
1986                                           "");
1987         }
1988
1989         result = delete_printer_handle(p, r->in.handle);
1990
1991         return result;
1992 }
1993
1994 /*******************************************************************
1995  * static function to lookup the version id corresponding to an
1996  * long architecture string
1997  ******************************************************************/
1998
1999 static const struct print_architecture_table_node archi_table[]= {
2000
2001         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2002         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2003         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2004         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2005         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2006         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2007         {"Windows x64",          SPL_ARCH_X64,          3 },
2008         {NULL,                   "",            -1 }
2009 };
2010
2011 static int get_version_id(const char *arch)
2012 {
2013         int i;
2014
2015         for (i=0; archi_table[i].long_archi != NULL; i++)
2016         {
2017                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2018                         return (archi_table[i].version);
2019         }
2020
2021         return -1;
2022 }
2023
2024 /****************************************************************
2025  _spoolss_DeletePrinterDriver
2026 ****************************************************************/
2027
2028 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2029                                     struct spoolss_DeletePrinterDriver *r)
2030 {
2031
2032         struct spoolss_DriverInfo8 *info = NULL;
2033         struct spoolss_DriverInfo8 *info_win2k = NULL;
2034         int                             version;
2035         WERROR                          status;
2036
2037         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2038            and not a printer admin, then fail */
2039
2040         if ( (p->server_info->utok.uid != sec_initial_uid())
2041              && !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR)
2042                 && !token_contains_name_in_list(
2043                         uidtoname(p->server_info->utok.uid),
2044                         p->server_info->info3->base.domain.string,
2045                         NULL,
2046                         p->server_info->ptok,
2047                         lp_printer_admin(-1)) )
2048         {
2049                 return WERR_ACCESS_DENIED;
2050         }
2051
2052         /* check that we have a valid driver name first */
2053
2054         if ((version = get_version_id(r->in.architecture)) == -1)
2055                 return WERR_INVALID_ENVIRONMENT;
2056
2057         status = winreg_get_driver(p->mem_ctx,
2058                                    get_server_info_system(),
2059                                    p->msg_ctx,
2060                                    r->in.architecture, r->in.driver,
2061                                    version, &info);
2062         if (!W_ERROR_IS_OK(status)) {
2063                 /* try for Win2k driver if "Windows NT x86" */
2064
2065                 if ( version == 2 ) {
2066                         version = 3;
2067
2068                         status = winreg_get_driver(p->mem_ctx,
2069                                                    get_server_info_system(),
2070                                                    p->msg_ctx,
2071                                                    r->in.architecture,
2072                                                    r->in.driver,
2073                                                    version, &info);
2074                         if (!W_ERROR_IS_OK(status)) {
2075                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2076                                 goto done;
2077                         }
2078                 }
2079                 /* otherwise it was a failure */
2080                 else {
2081                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2082                         goto done;
2083                 }
2084
2085         }
2086
2087         if (printer_driver_in_use(p->mem_ctx,
2088                                   get_server_info_system(),
2089                                   p->msg_ctx,
2090                                   info)) {
2091                 status = WERR_PRINTER_DRIVER_IN_USE;
2092                 goto done;
2093         }
2094
2095         if (version == 2) {
2096                 status = winreg_get_driver(p->mem_ctx,
2097                                            get_server_info_system(),
2098                                            p->msg_ctx,
2099                                            r->in.architecture,
2100                                            r->in.driver, 3, &info_win2k);
2101                 if (W_ERROR_IS_OK(status)) {
2102                         /* if we get to here, we now have 2 driver info structures to remove */
2103                         /* remove the Win2k driver first*/
2104
2105                         status = winreg_del_driver(p->mem_ctx,
2106                                                    get_server_info_system(),
2107                                                    p->msg_ctx,
2108                                                    info_win2k, 3);
2109                         talloc_free(info_win2k);
2110
2111                         /* this should not have failed---if it did, report to client */
2112                         if (!W_ERROR_IS_OK(status)) {
2113                                 goto done;
2114                         }
2115                 }
2116         }
2117
2118         status = winreg_del_driver(p->mem_ctx,
2119                                    get_server_info_system(),
2120                                    p->msg_ctx,
2121                                    info, version);
2122
2123 done:
2124         talloc_free(info);
2125
2126         return status;
2127 }
2128
2129 /****************************************************************
2130  _spoolss_DeletePrinterDriverEx
2131 ****************************************************************/
2132
2133 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2134                                       struct spoolss_DeletePrinterDriverEx *r)
2135 {
2136         struct spoolss_DriverInfo8      *info = NULL;
2137         struct spoolss_DriverInfo8      *info_win2k = NULL;
2138         int                             version;
2139         bool                            delete_files;
2140         WERROR                          status;
2141
2142         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2143            and not a printer admin, then fail */
2144
2145         if ( (p->server_info->utok.uid != sec_initial_uid())
2146                 && !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR)
2147                 && !token_contains_name_in_list(
2148                         uidtoname(p->server_info->utok.uid),
2149                         p->server_info->info3->base.domain.string,
2150                         NULL,
2151                         p->server_info->ptok, lp_printer_admin(-1)) )
2152         {
2153                 return WERR_ACCESS_DENIED;
2154         }
2155
2156         /* check that we have a valid driver name first */
2157         if ((version = get_version_id(r->in.architecture)) == -1) {
2158                 /* this is what NT returns */
2159                 return WERR_INVALID_ENVIRONMENT;
2160         }
2161
2162         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2163                 version = r->in.version;
2164
2165         status = winreg_get_driver(p->mem_ctx,
2166                                    get_server_info_system(),
2167                                    p->msg_ctx,
2168                                    r->in.architecture,
2169                                    r->in.driver,
2170                                    version,
2171                                    &info);
2172         if (!W_ERROR_IS_OK(status)) {
2173                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2174
2175                 /*
2176                  * if the client asked for a specific version,
2177                  * or this is something other than Windows NT x86,
2178                  * then we've failed
2179                  */
2180
2181                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2182                         goto done;
2183
2184                 /* try for Win2k driver if "Windows NT x86" */
2185
2186                 version = 3;
2187                 status = winreg_get_driver(info,
2188                                            get_server_info_system(),
2189                                            p->msg_ctx,
2190                                            r->in.architecture,
2191                                            r->in.driver,
2192                                            version, &info);
2193                 if (!W_ERROR_IS_OK(status)) {
2194                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2195                         goto done;
2196                 }
2197         }
2198
2199         if (printer_driver_in_use(info,
2200                                   get_server_info_system(),
2201                                   p->msg_ctx,
2202                                   info)) {
2203                 status = WERR_PRINTER_DRIVER_IN_USE;
2204                 goto done;
2205         }
2206
2207         /*
2208          * we have a couple of cases to consider.
2209          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2210          *     then the delete should fail if **any** files overlap with
2211          *     other drivers
2212          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2213          *     non-overlapping files
2214          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2215          *     is set, the do not delete any files
2216          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2217          */
2218
2219         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2220
2221         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2222
2223         if (delete_files &&
2224             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2225             printer_driver_files_in_use(info,
2226                                         get_server_info_system(),
2227                                         p->msg_ctx,
2228                                         info)) {
2229                 /* no idea of the correct error here */
2230                 status = WERR_ACCESS_DENIED;
2231                 goto done;
2232         }
2233
2234
2235         /* also check for W32X86/3 if necessary; maybe we already have? */
2236
2237         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2238                 status = winreg_get_driver(info,
2239                                            get_server_info_system(),
2240                                            p->msg_ctx,
2241                                            r->in.architecture,
2242                                            r->in.driver, 3, &info_win2k);
2243                 if (W_ERROR_IS_OK(status)) {
2244
2245                         if (delete_files &&
2246                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2247                             printer_driver_files_in_use(info,
2248                                                         get_server_info_system(),
2249                                                         p->msg_ctx,
2250                                                         info_win2k)) {
2251                                 /* no idea of the correct error here */
2252                                 talloc_free(info_win2k);
2253                                 status = WERR_ACCESS_DENIED;
2254                                 goto done;
2255                         }
2256
2257                         /* if we get to here, we now have 2 driver info structures to remove */
2258                         /* remove the Win2k driver first*/
2259
2260                         status = winreg_del_driver(info,
2261                                                    get_server_info_system(),
2262                                                    p->msg_ctx,
2263                                                    info_win2k,
2264                                                    3);
2265
2266                         /* this should not have failed---if it did, report to client */
2267
2268                         if (!W_ERROR_IS_OK(status)) {
2269                                 goto done;
2270                         }
2271
2272                         /*
2273                          * now delete any associated files if delete_files is
2274                          * true. Even if this part failes, we return succes
2275                          * because the driver doesn not exist any more
2276                          */
2277                         if (delete_files) {
2278                                 delete_driver_files(get_server_info_system(),
2279                                                     info_win2k);
2280                         }
2281                 }
2282         }
2283
2284         status = winreg_del_driver(info,
2285                                    get_server_info_system(),
2286                                    p->msg_ctx,
2287                                    info,
2288                                    version);
2289         if (!W_ERROR_IS_OK(status)) {
2290                 goto done;
2291         }
2292
2293         /*
2294          * now delete any associated files if delete_files is
2295          * true. Even if this part failes, we return succes
2296          * because the driver doesn not exist any more
2297          */
2298         if (delete_files) {
2299                 delete_driver_files(get_server_info_system(), info);
2300         }
2301
2302 done:
2303         talloc_free(info);
2304         return status;
2305 }
2306
2307
2308 /********************************************************************
2309  GetPrinterData on a printer server Handle.
2310 ********************************************************************/
2311
2312 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2313                                             const char *value,
2314                                             enum winreg_Type *type,
2315                                             union spoolss_PrinterData *data)
2316 {
2317         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2318
2319         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2320                 *type = REG_DWORD;
2321                 data->value = 0x00;
2322                 return WERR_OK;
2323         }
2324
2325         if (!StrCaseCmp(value, "BeepEnabled")) {
2326                 *type = REG_DWORD;
2327                 data->value = 0x00;
2328                 return WERR_OK;
2329         }
2330
2331         if (!StrCaseCmp(value, "EventLog")) {
2332                 *type = REG_DWORD;
2333                 /* formally was 0x1b */
2334                 data->value = 0x00;
2335                 return WERR_OK;
2336         }
2337
2338         if (!StrCaseCmp(value, "NetPopup")) {
2339                 *type = REG_DWORD;
2340                 data->value = 0x00;
2341                 return WERR_OK;
2342         }
2343
2344         if (!StrCaseCmp(value, "MajorVersion")) {
2345                 *type = REG_DWORD;
2346
2347                 /* Windows NT 4.0 seems to not allow uploading of drivers
2348                    to a server that reports 0x3 as the MajorVersion.
2349                    need to investigate more how Win2k gets around this .
2350                    -- jerry */
2351
2352                 if (RA_WINNT == get_remote_arch()) {
2353                         data->value = 0x02;
2354                 } else {
2355                         data->value = 0x03;
2356                 }
2357
2358                 return WERR_OK;
2359         }
2360
2361         if (!StrCaseCmp(value, "MinorVersion")) {
2362                 *type = REG_DWORD;
2363                 data->value = 0x00;
2364                 return WERR_OK;
2365         }
2366
2367         /* REG_BINARY
2368          *  uint32_t size        = 0x114
2369          *  uint32_t major       = 5
2370          *  uint32_t minor       = [0|1]
2371          *  uint32_t build       = [2195|2600]
2372          *  extra unicode string = e.g. "Service Pack 3"
2373          */
2374         if (!StrCaseCmp(value, "OSVersion")) {
2375                 DATA_BLOB blob;
2376                 enum ndr_err_code ndr_err;
2377                 struct spoolss_OSVersion os;
2378
2379                 os.major                = 5;    /* Windows 2000 == 5.0 */
2380                 os.minor                = 0;
2381                 os.build                = 2195; /* build */
2382                 os.extra_string         = "";   /* leave extra string empty */
2383
2384                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2385                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2386                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2387                         return WERR_GENERAL_FAILURE;
2388                 }
2389
2390                 *type = REG_BINARY;
2391                 data->binary = blob;
2392
2393                 return WERR_OK;
2394         }
2395
2396
2397         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2398                 *type = REG_SZ;
2399
2400                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2401                 W_ERROR_HAVE_NO_MEMORY(data->string);
2402
2403                 return WERR_OK;
2404         }
2405
2406         if (!StrCaseCmp(value, "Architecture")) {
2407                 *type = REG_SZ;
2408                 data->string = talloc_strdup(mem_ctx,
2409                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2410                 W_ERROR_HAVE_NO_MEMORY(data->string);
2411
2412                 return WERR_OK;
2413         }
2414
2415         if (!StrCaseCmp(value, "DsPresent")) {
2416                 *type = REG_DWORD;
2417
2418                 /* only show the publish check box if we are a
2419                    member of a AD domain */
2420
2421                 if (lp_security() == SEC_ADS) {
2422                         data->value = 0x01;
2423                 } else {
2424                         data->value = 0x00;
2425                 }
2426                 return WERR_OK;
2427         }
2428
2429         if (!StrCaseCmp(value, "DNSMachineName")) {
2430                 const char *hostname = get_mydnsfullname();
2431
2432                 if (!hostname) {
2433                         return WERR_BADFILE;
2434                 }
2435
2436                 *type = REG_SZ;
2437                 data->string = talloc_strdup(mem_ctx, hostname);
2438                 W_ERROR_HAVE_NO_MEMORY(data->string);
2439
2440                 return WERR_OK;
2441         }
2442
2443         *type = REG_NONE;
2444
2445         return WERR_INVALID_PARAM;
2446 }
2447
2448 /****************************************************************
2449  _spoolss_GetPrinterData
2450 ****************************************************************/
2451
2452 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2453                                struct spoolss_GetPrinterData *r)
2454 {
2455         struct spoolss_GetPrinterDataEx r2;
2456
2457         r2.in.handle            = r->in.handle;
2458         r2.in.key_name          = "PrinterDriverData";
2459         r2.in.value_name        = r->in.value_name;
2460         r2.in.offered           = r->in.offered;
2461         r2.out.type             = r->out.type;
2462         r2.out.data             = r->out.data;
2463         r2.out.needed           = r->out.needed;
2464
2465         return _spoolss_GetPrinterDataEx(p, &r2);
2466 }
2467
2468 /*********************************************************
2469  Connect to the client machine.
2470 **********************************************************/
2471
2472 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2473                         struct sockaddr_storage *client_ss, const char *remote_machine)
2474 {
2475         NTSTATUS ret;
2476         struct cli_state *the_cli;
2477         struct sockaddr_storage rm_addr;
2478         char addr[INET6_ADDRSTRLEN];
2479
2480         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2481                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2482                         remote_machine));
2483                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2484                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2485                         return false;
2486                 }
2487                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2488         } else {
2489                 rm_addr = *client_ss;
2490                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2491                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2492                         addr));
2493         }
2494
2495         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2496                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2497                         addr));
2498                 return false;
2499         }
2500
2501         /* setup the connection */
2502         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2503                 &rm_addr, 0, "IPC$", "IPC",
2504                 "", /* username */
2505                 "", /* domain */
2506                 "", /* password */
2507                 0, lp_client_signing(), NULL );
2508
2509         if ( !NT_STATUS_IS_OK( ret ) ) {
2510                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2511                         remote_machine ));
2512                 return false;
2513         }
2514
2515         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2516                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2517                 cli_shutdown(the_cli);
2518                 return false;
2519         }
2520
2521         /*
2522          * Ok - we have an anonymous connection to the IPC$ share.
2523          * Now start the NT Domain stuff :-).
2524          */
2525
2526         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2527         if (!NT_STATUS_IS_OK(ret)) {
2528                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2529                         remote_machine, nt_errstr(ret)));
2530                 cli_shutdown(the_cli);
2531                 return false;
2532         }
2533
2534         return true;
2535 }
2536
2537 /***************************************************************************
2538  Connect to the client.
2539 ****************************************************************************/
2540
2541 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2542                                         uint32_t localprinter,
2543                                         enum winreg_Type type,
2544                                         struct policy_handle *handle,
2545                                         struct notify_back_channel **_chan,
2546                                         struct sockaddr_storage *client_ss,
2547                                         struct messaging_context *msg_ctx)
2548 {
2549         WERROR result;
2550         NTSTATUS status;
2551         struct notify_back_channel *chan;
2552
2553         for (chan = back_channels; chan; chan = chan->next) {
2554                 if (memcmp(&chan->client_address, client_ss,
2555                            sizeof(struct sockaddr_storage)) == 0) {
2556                         break;
2557                 }
2558         }
2559
2560         /*
2561          * If it's the first connection, contact the client
2562          * and connect to the IPC$ share anonymously
2563          */
2564         if (!chan) {
2565                 fstring unix_printer;
2566
2567                 /* the +2 is to strip the leading 2 backslashs */
2568                 fstrcpy(unix_printer, printer + 2);
2569
2570                 chan = talloc_zero(back_channels, struct notify_back_channel);
2571                 if (!chan) {
2572                         return false;
2573                 }
2574                 chan->client_address = *client_ss;
2575
2576                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2577                         TALLOC_FREE(chan);
2578                         return false;
2579                 }
2580
2581                 DLIST_ADD(back_channels, chan);
2582
2583                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2584                                    receive_notify2_message_list);
2585                 /* Tell the connections db we're now interested in printer
2586                  * notify messages. */
2587                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2588                                             true, FLAG_MSG_PRINT_NOTIFY);
2589         }
2590
2591         /*
2592          * Tell the specific printing tdb we want messages for this printer
2593          * by registering our PID.
2594          */
2595
2596         if (!print_notify_register_pid(snum)) {
2597                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2598                           printer));
2599         }
2600
2601         status = rpccli_spoolss_ReplyOpenPrinter(chan->cli_pipe, talloc_tos(),
2602                                                  printer,
2603                                                  localprinter,
2604                                                  type,
2605                                                  0,
2606                                                  NULL,
2607                                                  handle,
2608                                                  &result);
2609         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
2610                 DEBUG(5, ("Client RPC returned [%s]\n", win_errstr(result)));
2611         }
2612
2613         chan->active_connections++;
2614         *_chan = chan;
2615
2616         return (W_ERROR_IS_OK(result));
2617 }
2618
2619 /****************************************************************
2620  ****************************************************************/
2621
2622 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2623                                                              const struct spoolss_NotifyOption *r)
2624 {
2625         struct spoolss_NotifyOption *option;
2626         uint32_t i,k;
2627
2628         if (!r) {
2629                 return NULL;
2630         }
2631
2632         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2633         if (!option) {
2634                 return NULL;
2635         }
2636
2637         *option = *r;
2638
2639         if (!option->count) {
2640                 return option;
2641         }
2642
2643         option->types = talloc_zero_array(option,
2644                 struct spoolss_NotifyOptionType, option->count);
2645         if (!option->types) {
2646                 talloc_free(option);
2647                 return NULL;
2648         }
2649
2650         for (i=0; i < option->count; i++) {
2651                 option->types[i] = r->types[i];
2652
2653                 if (option->types[i].count) {
2654                         option->types[i].fields = talloc_zero_array(option,
2655                                 union spoolss_Field, option->types[i].count);
2656                         if (!option->types[i].fields) {
2657                                 talloc_free(option);
2658                                 return NULL;
2659                         }
2660                         for (k=0; k<option->types[i].count; k++) {
2661                                 option->types[i].fields[k] =
2662                                         r->types[i].fields[k];
2663                         }
2664                 }
2665         }
2666
2667         return option;
2668 }
2669
2670 /****************************************************************
2671  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2672  *
2673  * before replying OK: status=0 a rpc call is made to the workstation
2674  * asking ReplyOpenPrinter
2675  *
2676  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2677  * called from api_spoolss_rffpcnex
2678 ****************************************************************/
2679
2680 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2681                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2682 {
2683         int snum = -1;
2684         struct spoolss_NotifyOption *option = r->in.notify_options;
2685         struct sockaddr_storage client_ss;
2686
2687         /* store the notify value in the printer struct */
2688
2689         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2690
2691         if (!Printer) {
2692                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2693                         "Invalid handle (%s:%u:%u).\n",
2694                         OUR_HANDLE(r->in.handle)));
2695                 return WERR_BADFID;
2696         }
2697
2698         Printer->notify.flags           = r->in.flags;
2699         Printer->notify.options         = r->in.options;
2700         Printer->notify.printerlocal    = r->in.printer_local;
2701         Printer->notify.msg_ctx         = p->msg_ctx;
2702
2703         TALLOC_FREE(Printer->notify.option);
2704         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2705
2706         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2707
2708         /* Connect to the client machine and send a ReplyOpenPrinter */
2709
2710         if ( Printer->printer_type == SPLHND_SERVER)
2711                 snum = -1;
2712         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2713                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2714                 return WERR_BADFID;
2715
2716         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2717                 "client_address is %s\n", p->client_id->addr));
2718
2719         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2720                                    AI_NUMERICHOST)) {
2721                 return WERR_SERVER_UNAVAILABLE;
2722         }
2723
2724         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2725                                         Printer->notify.printerlocal, REG_SZ,
2726                                         &Printer->notify.cli_hnd,
2727                                         &Printer->notify.cli_chan,
2728                                         &client_ss, p->msg_ctx)) {
2729                 return WERR_SERVER_UNAVAILABLE;
2730         }
2731
2732         return WERR_OK;
2733 }
2734
2735 /*******************************************************************
2736  * fill a notify_info_data with the servername
2737  ********************************************************************/
2738
2739 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2740                                        int snum,
2741                                        struct spoolss_Notify *data,
2742                                        print_queue_struct *queue,
2743                                        struct spoolss_PrinterInfo2 *pinfo2,
2744                                        TALLOC_CTX *mem_ctx)
2745 {
2746         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2747 }
2748
2749 /*******************************************************************
2750  * fill a notify_info_data with the printername (not including the servername).
2751  ********************************************************************/
2752
2753 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2754                                         int snum,
2755                                         struct spoolss_Notify *data,
2756                                         print_queue_struct *queue,
2757                                         struct spoolss_PrinterInfo2 *pinfo2,
2758                                         TALLOC_CTX *mem_ctx)
2759 {
2760         /* the notify name should not contain the \\server\ part */
2761         const char *p = strrchr(pinfo2->printername, '\\');
2762
2763         if (!p) {
2764                 p = pinfo2->printername;
2765         } else {
2766                 p++;
2767         }
2768
2769         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2770 }
2771
2772 /*******************************************************************
2773  * fill a notify_info_data with the servicename
2774  ********************************************************************/
2775
2776 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2777                                       int snum,
2778                                       struct spoolss_Notify *data,
2779                                       print_queue_struct *queue,
2780                                       struct spoolss_PrinterInfo2 *pinfo2,
2781                                       TALLOC_CTX *mem_ctx)
2782 {
2783         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2784 }
2785
2786 /*******************************************************************
2787  * fill a notify_info_data with the port name
2788  ********************************************************************/
2789
2790 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2791                                      int snum,
2792                                      struct spoolss_Notify *data,
2793                                      print_queue_struct *queue,
2794                                      struct spoolss_PrinterInfo2 *pinfo2,
2795                                      TALLOC_CTX *mem_ctx)
2796 {
2797         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2798 }
2799
2800 /*******************************************************************
2801  * fill a notify_info_data with the printername
2802  * but it doesn't exist, have to see what to do
2803  ********************************************************************/
2804
2805 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2806                                        int snum,
2807                                        struct spoolss_Notify *data,
2808                                        print_queue_struct *queue,
2809                                        struct spoolss_PrinterInfo2 *pinfo2,
2810                                        TALLOC_CTX *mem_ctx)
2811 {
2812         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2813 }
2814
2815 /*******************************************************************
2816  * fill a notify_info_data with the comment
2817  ********************************************************************/
2818
2819 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2820                                    int snum,
2821                                    struct spoolss_Notify *data,
2822                                    print_queue_struct *queue,
2823                                    struct spoolss_PrinterInfo2 *pinfo2,
2824                                    TALLOC_CTX *mem_ctx)
2825 {
2826         const char *p;
2827
2828         if (*pinfo2->comment == '\0') {
2829                 p = lp_comment(snum);
2830         } else {
2831                 p = pinfo2->comment;
2832         }
2833
2834         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2835 }
2836
2837 /*******************************************************************
2838  * fill a notify_info_data with the comment
2839  * location = "Room 1, floor 2, building 3"
2840  ********************************************************************/
2841
2842 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2843                                     int snum,
2844                                     struct spoolss_Notify *data,
2845                                     print_queue_struct *queue,
2846                                     struct spoolss_PrinterInfo2 *pinfo2,
2847                                     TALLOC_CTX *mem_ctx)
2848 {
2849         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2850 }
2851
2852 /*******************************************************************
2853  * fill a notify_info_data with the device mode
2854  * jfm:xxxx don't to it for know but that's a real problem !!!
2855  ********************************************************************/
2856
2857 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2858                                    int snum,
2859                                    struct spoolss_Notify *data,
2860                                    print_queue_struct *queue,
2861                                    struct spoolss_PrinterInfo2 *pinfo2,
2862                                    TALLOC_CTX *mem_ctx)
2863 {
2864         /* for a dummy implementation we have to zero the fields */
2865         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2866 }
2867
2868 /*******************************************************************
2869  * fill a notify_info_data with the separator file name
2870  ********************************************************************/
2871
2872 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2873                                    int snum,
2874                                    struct spoolss_Notify *data,
2875                                    print_queue_struct *queue,
2876                                    struct spoolss_PrinterInfo2 *pinfo2,
2877                                    TALLOC_CTX *mem_ctx)
2878 {
2879         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2880 }
2881
2882 /*******************************************************************
2883  * fill a notify_info_data with the print processor
2884  * jfm:xxxx return always winprint to indicate we don't do anything to it
2885  ********************************************************************/
2886
2887 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2888                                            int snum,
2889                                            struct spoolss_Notify *data,
2890                                            print_queue_struct *queue,
2891                                            struct spoolss_PrinterInfo2 *pinfo2,
2892                                            TALLOC_CTX *mem_ctx)
2893 {
2894         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2895 }
2896
2897 /*******************************************************************
2898  * fill a notify_info_data with the print processor options
2899  * jfm:xxxx send an empty string
2900  ********************************************************************/
2901
2902 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2903                                       int snum,
2904                                       struct spoolss_Notify *data,
2905                                       print_queue_struct *queue,
2906                                       struct spoolss_PrinterInfo2 *pinfo2,
2907                                       TALLOC_CTX *mem_ctx)
2908 {
2909         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2910 }
2911
2912 /*******************************************************************
2913  * fill a notify_info_data with the data type
2914  * jfm:xxxx always send RAW as data type
2915  ********************************************************************/
2916
2917 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2918                                     int snum,
2919                                     struct spoolss_Notify *data,
2920                                     print_queue_struct *queue,
2921                                     struct spoolss_PrinterInfo2 *pinfo2,
2922                                     TALLOC_CTX *mem_ctx)
2923 {
2924         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2925 }
2926
2927 /*******************************************************************
2928  * fill a notify_info_data with the security descriptor
2929  * jfm:xxxx send an null pointer to say no security desc
2930  * have to implement security before !
2931  ********************************************************************/
2932
2933 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2934                                          int snum,
2935                                          struct spoolss_Notify *data,
2936                                          print_queue_struct *queue,
2937                                          struct spoolss_PrinterInfo2 *pinfo2,
2938                                          TALLOC_CTX *mem_ctx)
2939 {
2940         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2941 }
2942
2943 /*******************************************************************
2944  * fill a notify_info_data with the attributes
2945  * jfm:xxxx a samba printer is always shared
2946  ********************************************************************/
2947
2948 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2949                                       int snum,
2950                                       struct spoolss_Notify *data,
2951                                       print_queue_struct *queue,
2952                                       struct spoolss_PrinterInfo2 *pinfo2,
2953                                       TALLOC_CTX *mem_ctx)
2954 {
2955         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2956 }
2957
2958 /*******************************************************************
2959  * fill a notify_info_data with the priority
2960  ********************************************************************/
2961
2962 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2963                                     int snum,
2964                                     struct spoolss_Notify *data,
2965                                     print_queue_struct *queue,
2966                                     struct spoolss_PrinterInfo2 *pinfo2,
2967                                     TALLOC_CTX *mem_ctx)
2968 {
2969         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2970 }
2971
2972 /*******************************************************************
2973  * fill a notify_info_data with the default priority
2974  ********************************************************************/
2975
2976 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2977                                             int snum,
2978                                             struct spoolss_Notify *data,
2979                                             print_queue_struct *queue,
2980                                             struct spoolss_PrinterInfo2 *pinfo2,
2981                                             TALLOC_CTX *mem_ctx)
2982 {
2983         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2984 }
2985
2986 /*******************************************************************
2987  * fill a notify_info_data with the start time
2988  ********************************************************************/
2989
2990 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2991                                       int snum,
2992                                       struct spoolss_Notify *data,
2993                                       print_queue_struct *queue,
2994                                       struct spoolss_PrinterInfo2 *pinfo2,
2995                                       TALLOC_CTX *mem_ctx)
2996 {
2997         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2998 }
2999
3000 /*******************************************************************
3001  * fill a notify_info_data with the until time
3002  ********************************************************************/
3003
3004 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3005                                       int snum,
3006                                       struct spoolss_Notify *data,
3007                                       print_queue_struct *queue,
3008                                       struct spoolss_PrinterInfo2 *pinfo2,
3009                                       TALLOC_CTX *mem_ctx)
3010 {
3011         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3012 }
3013
3014 /*******************************************************************
3015  * fill a notify_info_data with the status
3016  ********************************************************************/
3017
3018 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3019                                   int snum,
3020                                   struct spoolss_Notify *data,
3021                                   print_queue_struct *queue,
3022                                   struct spoolss_PrinterInfo2 *pinfo2,
3023                                   TALLOC_CTX *mem_ctx)
3024 {
3025         print_status_struct status;
3026
3027         print_queue_length(msg_ctx, snum, &status);
3028         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3029 }
3030
3031 /*******************************************************************
3032  * fill a notify_info_data with the number of jobs queued
3033  ********************************************************************/
3034
3035 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3036                                  int snum,
3037                                  struct spoolss_Notify *data,
3038                                  print_queue_struct *queue,
3039                                  struct spoolss_PrinterInfo2 *pinfo2,
3040                                  TALLOC_CTX *mem_ctx)
3041 {
3042         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3043                 data, print_queue_length(msg_ctx, snum, NULL));
3044 }
3045
3046 /*******************************************************************
3047  * fill a notify_info_data with the average ppm
3048  ********************************************************************/
3049
3050 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3051                                        int snum,
3052                                        struct spoolss_Notify *data,
3053                                        print_queue_struct *queue,
3054                                        struct spoolss_PrinterInfo2 *pinfo2,
3055                                        TALLOC_CTX *mem_ctx)
3056 {
3057         /* always respond 8 pages per minutes */
3058         /* a little hard ! */
3059         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3060 }
3061
3062 /*******************************************************************
3063  * fill a notify_info_data with username
3064  ********************************************************************/
3065
3066 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3067                                     int snum,
3068                                     struct spoolss_Notify *data,
3069                                     print_queue_struct *queue,
3070                                     struct spoolss_PrinterInfo2 *pinfo2,
3071                                     TALLOC_CTX *mem_ctx)
3072 {
3073         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3074 }
3075
3076 /*******************************************************************
3077  * fill a notify_info_data with job status
3078  ********************************************************************/
3079
3080 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3081                                       int snum,
3082                                       struct spoolss_Notify *data,
3083                                       print_queue_struct *queue,
3084                                       struct spoolss_PrinterInfo2 *pinfo2,
3085                                       TALLOC_CTX *mem_ctx)
3086 {
3087         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3088 }
3089
3090 /*******************************************************************
3091  * fill a notify_info_data with job name
3092  ********************************************************************/
3093
3094 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3095                                     int snum,
3096                                     struct spoolss_Notify *data,
3097                                     print_queue_struct *queue,
3098                                     struct spoolss_PrinterInfo2 *pinfo2,
3099                                     TALLOC_CTX *mem_ctx)
3100 {
3101         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3102 }
3103
3104 /*******************************************************************
3105  * fill a notify_info_data with job status
3106  ********************************************************************/
3107
3108 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3109                                              int snum,
3110                                              struct spoolss_Notify *data,
3111                                              print_queue_struct *queue,
3112                                              struct spoolss_PrinterInfo2 *pinfo2,
3113                                              TALLOC_CTX *mem_ctx)
3114 {
3115         /*
3116          * Now we're returning job status codes we just return a "" here. JRA.
3117          */
3118
3119         const char *p = "";
3120
3121 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3122         p = "unknown";
3123
3124         switch (queue->status) {
3125         case LPQ_QUEUED:
3126                 p = "Queued";
3127                 break;
3128         case LPQ_PAUSED:
3129                 p = "";    /* NT provides the paused string */
3130                 break;
3131         case LPQ_SPOOLING:
3132                 p = "Spooling";
3133                 break;
3134         case LPQ_PRINTING:
3135                 p = "Printing";
3136                 break;
3137         }
3138 #endif /* NO LONGER NEEDED. */
3139
3140         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3141 }
3142
3143 /*******************************************************************
3144  * fill a notify_info_data with job time
3145  ********************************************************************/
3146
3147 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3148                                     int snum,
3149                                     struct spoolss_Notify *data,
3150                                     print_queue_struct *queue,
3151                                     struct spoolss_PrinterInfo2 *pinfo2,
3152                                     TALLOC_CTX *mem_ctx)
3153 {
3154         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3155 }
3156
3157 /*******************************************************************
3158  * fill a notify_info_data with job size
3159  ********************************************************************/
3160
3161 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3162                                     int snum,
3163                                     struct spoolss_Notify *data,
3164                                     print_queue_struct *queue,
3165                                     struct spoolss_PrinterInfo2 *pinfo2,
3166                                     TALLOC_CTX *mem_ctx)
3167 {
3168         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3169 }
3170
3171 /*******************************************************************
3172  * fill a notify_info_data with page info
3173  ********************************************************************/
3174 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3175                                        int snum,
3176                                 struct spoolss_Notify *data,
3177                                 print_queue_struct *queue,
3178                                 struct spoolss_PrinterInfo2 *pinfo2,
3179                                 TALLOC_CTX *mem_ctx)
3180 {
3181         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3182 }
3183
3184 /*******************************************************************
3185  * fill a notify_info_data with pages printed info.
3186  ********************************************************************/
3187 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3188                                          int snum,
3189                                 struct spoolss_Notify *data,
3190                                 print_queue_struct *queue,
3191                                 struct spoolss_PrinterInfo2 *pinfo2,
3192                                 TALLOC_CTX *mem_ctx)
3193 {
3194         /* Add code when back-end tracks this */
3195         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3196 }
3197
3198 /*******************************************************************
3199  Fill a notify_info_data with job position.
3200  ********************************************************************/
3201
3202 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3203                                         int snum,
3204                                         struct spoolss_Notify *data,
3205                                         print_queue_struct *queue,
3206                                         struct spoolss_PrinterInfo2 *pinfo2,
3207                                         TALLOC_CTX *mem_ctx)
3208 {
3209         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3210 }
3211
3212 /*******************************************************************
3213  Fill a notify_info_data with submitted time.
3214  ********************************************************************/
3215
3216 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3217                                           int snum,
3218                                           struct spoolss_Notify *data,
3219                                           print_queue_struct *queue,
3220                                           struct spoolss_PrinterInfo2 *pinfo2,
3221                                           TALLOC_CTX *mem_ctx)
3222 {
3223         data->data.string.string = NULL;
3224         data->data.string.size = 0;
3225
3226         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3227                                &data->data.string.string,
3228                                &data->data.string.size);
3229
3230 }
3231
3232 struct s_notify_info_data_table
3233 {
3234         enum spoolss_NotifyType type;
3235         uint16_t field;
3236         const char *name;
3237         enum spoolss_NotifyTable variable_type;
3238         void (*fn) (struct messaging_context *msg_ctx,
3239                     int snum, struct spoolss_Notify *data,
3240                     print_queue_struct *queue,
3241                     struct spoolss_PrinterInfo2 *pinfo2,
3242                     TALLOC_CTX *mem_ctx);
3243 };
3244
3245 /* A table describing the various print notification constants and
3246    whether the notification data is a pointer to a variable sized
3247    buffer, a one value uint32_t or a two value uint32_t. */
3248
3249 static const struct s_notify_info_data_table notify_info_data_table[] =
3250 {
3251 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3277 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3278 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3279 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3280 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3281 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3282 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3283 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3284 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3285 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3286 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3287 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3288 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3289 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3290 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3291 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3300 };
3301
3302 /*******************************************************************
3303  Return the variable_type of info_data structure.
3304 ********************************************************************/
3305
3306 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3307                                                                   uint16_t field)
3308 {
3309         int i=0;
3310
3311         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3312                 if ( (notify_info_data_table[i].type == type) &&
3313                      (notify_info_data_table[i].field == field) ) {
3314                         return notify_info_data_table[i].variable_type;
3315                 }
3316         }
3317
3318         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3319
3320         return (enum spoolss_NotifyTable) 0;
3321 }
3322
3323 /****************************************************************************
3324 ****************************************************************************/
3325
3326 static bool search_notify(enum spoolss_NotifyType type,
3327                           uint16_t field,
3328                           int *value)
3329 {
3330         int i;
3331
3332         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3333                 if (notify_info_data_table[i].type == type &&
3334                     notify_info_data_table[i].field == field &&
3335                     notify_info_data_table[i].fn != NULL) {
3336                         *value = i;
3337                         return true;
3338                 }
3339         }
3340
3341         return false;
3342 }
3343
3344 /****************************************************************************
3345 ****************************************************************************/
3346
3347 static void construct_info_data(struct spoolss_Notify *info_data,
3348                                 enum spoolss_NotifyType type,
3349                                 uint16_t field, int id)
3350 {
3351         info_data->type                 = type;
3352         info_data->field.field          = field;
3353         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3354         info_data->job_id               = id;
3355 }
3356
3357 /*******************************************************************
3358  *
3359  * fill a notify_info struct with info asked
3360  *
3361  ********************************************************************/
3362
3363 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3364                                           struct printer_handle *print_hnd,
3365                                           struct spoolss_NotifyInfo *info,
3366                                           struct spoolss_PrinterInfo2 *pinfo2,
3367                                           int snum,
3368                                           const struct spoolss_NotifyOptionType *option_type,
3369                                           uint32_t id,
3370                                           TALLOC_CTX *mem_ctx)
3371 {
3372         int field_num,j;
3373         enum spoolss_NotifyType type;
3374         uint16_t field;
3375
3376         struct spoolss_Notify *current_data;
3377         print_queue_struct *queue=NULL;
3378
3379         type = option_type->type;
3380
3381         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3382                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3383                 option_type->count, lp_servicename(snum)));
3384
3385         for(field_num=0; field_num < option_type->count; field_num++) {
3386                 field = option_type->fields[field_num].field;
3387
3388                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3389
3390                 if (!search_notify(type, field, &j) )
3391                         continue;
3392
3393                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3394                                                       struct spoolss_Notify,
3395                                                       info->count + 1);
3396                 if (info->notifies == NULL) {
3397                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3398                         return false;
3399                 }
3400
3401                 current_data = &info->notifies[info->count];
3402
3403                 construct_info_data(current_data, type, field, id);
3404
3405                 DEBUG(10, ("construct_notify_printer_info: "
3406                            "calling [%s]  snum=%d  printername=[%s])\n",
3407                            notify_info_data_table[j].name, snum,
3408                            pinfo2->printername));
3409
3410                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3411                                              queue, pinfo2, mem_ctx);
3412
3413                 info->count++;
3414         }
3415
3416         return true;
3417 }
3418
3419 /*******************************************************************
3420  *
3421  * fill a notify_info struct with info asked
3422  *
3423  ********************************************************************/
3424
3425 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3426                                        print_queue_struct *queue,
3427                                        struct spoolss_NotifyInfo *info,
3428                                        struct spoolss_PrinterInfo2 *pinfo2,
3429                                        int snum,
3430                                        const struct spoolss_NotifyOptionType *option_type,
3431                                        uint32_t id,
3432                                        TALLOC_CTX *mem_ctx)
3433 {
3434         int field_num,j;
3435         enum spoolss_NotifyType type;
3436         uint16_t field;
3437         struct spoolss_Notify *current_data;
3438
3439         DEBUG(4,("construct_notify_jobs_info\n"));
3440
3441         type = option_type->type;
3442
3443         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3444                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3445                 option_type->count));
3446
3447         for(field_num=0; field_num<option_type->count; field_num++) {
3448                 field = option_type->fields[field_num].field;
3449
3450                 if (!search_notify(type, field, &j) )
3451                         continue;
3452
3453                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3454                                                       struct spoolss_Notify,
3455                                                       info->count + 1);
3456                 if (info->notifies == NULL) {
3457                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3458                         return false;
3459                 }
3460
3461                 current_data=&(info->notifies[info->count]);
3462
3463                 construct_info_data(current_data, type, field, id);
3464                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3465                                              queue, pinfo2, mem_ctx);
3466                 info->count++;
3467         }
3468
3469         return true;
3470 }
3471
3472 /*
3473  * JFM: The enumeration is not that simple, it's even non obvious.
3474  *
3475  * let's take an example: I want to monitor the PRINTER SERVER for
3476  * the printer's name and the number of jobs currently queued.
3477  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3478  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3479  *
3480  * I have 3 printers on the back of my server.
3481  *
3482  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3483  * structures.
3484  *   Number     Data                    Id
3485  *      1       printer 1 name          1
3486  *      2       printer 1 cjob          1
3487  *      3       printer 2 name          2
3488  *      4       printer 2 cjob          2
3489  *      5       printer 3 name          3
3490  *      6       printer 3 name          3
3491  *
3492  * that's the print server case, the printer case is even worse.
3493  */
3494
3495 /*******************************************************************
3496  *
3497  * enumerate all printers on the printserver
3498  * fill a notify_info struct with info asked
3499  *
3500  ********************************************************************/
3501
3502 static WERROR printserver_notify_info(struct pipes_struct *p,
3503                                       struct policy_handle *hnd,
3504                                       struct spoolss_NotifyInfo *info,
3505                                       TALLOC_CTX *mem_ctx)
3506 {
3507         int snum;
3508         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3509         int n_services=lp_numservices();
3510         int i;
3511         struct spoolss_NotifyOption *option;
3512         struct spoolss_NotifyOptionType option_type;
3513         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3514         WERROR result;
3515
3516         DEBUG(4,("printserver_notify_info\n"));
3517
3518         if (!Printer)
3519                 return WERR_BADFID;
3520
3521         option = Printer->notify.option;
3522
3523         info->version   = 2;
3524         info->notifies  = NULL;
3525         info->count     = 0;
3526
3527         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3528            sending a ffpcn() request first */
3529
3530         if ( !option )
3531                 return WERR_BADFID;
3532
3533         for (i=0; i<option->count; i++) {
3534                 option_type = option->types[i];
3535
3536                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3537                         continue;
3538
3539                 for (snum = 0; snum < n_services; snum++) {
3540                         if (!lp_browseable(snum) ||
3541                             !lp_snum_ok(snum) ||
3542                             !lp_print_ok(snum)) {
3543                                 continue; /* skip */
3544                         }
3545
3546                         /* Maybe we should use the SYSTEM server_info here... */
3547                         result = winreg_get_printer(mem_ctx,
3548                                                     get_server_info_system(),
3549                                                     p->msg_ctx,
3550                                                     lp_servicename(snum),
3551                                                     &pinfo2);
3552                         if (!W_ERROR_IS_OK(result)) {
3553                                 DEBUG(4, ("printserver_notify_info: "
3554                                           "Failed to get printer [%s]\n",
3555                                           lp_servicename(snum)));
3556                                 continue;
3557                         }
3558
3559
3560                         construct_notify_printer_info(p->msg_ctx,
3561                                                       Printer, info,
3562                                                       pinfo2, snum,
3563                                                       &option_type, snum,
3564                                                       mem_ctx);
3565
3566                         TALLOC_FREE(pinfo2);
3567                 }
3568         }
3569
3570 #if 0
3571         /*
3572          * Debugging information, don't delete.
3573          */
3574
3575         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3576         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3577         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3578
3579         for (i=0; i<info->count; i++) {
3580                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3581                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3582                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3583         }
3584 #endif
3585
3586         return WERR_OK;
3587 }
3588
3589 /*******************************************************************
3590  *
3591  * fill a notify_info struct with info asked
3592  *
3593  ********************************************************************/
3594
3595 static WERROR printer_notify_info(struct pipes_struct *p,
3596                                   struct policy_handle *hnd,
3597                                   struct spoolss_NotifyInfo *info,
3598                                   TALLOC_CTX *mem_ctx)
3599 {
3600         int snum;
3601         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3602         int i;
3603         uint32_t id;
3604         struct spoolss_NotifyOption *option;
3605         struct spoolss_NotifyOptionType option_type;
3606         int count,j;
3607         print_queue_struct *queue=NULL;
3608         print_status_struct status;
3609         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3610         WERROR result;
3611
3612         DEBUG(4,("printer_notify_info\n"));
3613
3614         if (!Printer)
3615                 return WERR_BADFID;
3616
3617         option = Printer->notify.option;
3618         id = 0x0;
3619
3620         info->version   = 2;
3621         info->notifies  = NULL;
3622         info->count     = 0;
3623
3624         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3625            sending a ffpcn() request first */
3626
3627         if ( !option )
3628                 return WERR_BADFID;
3629
3630         get_printer_snum(p, hnd, &snum, NULL);
3631
3632         /* Maybe we should use the SYSTEM server_info here... */
3633         result = winreg_get_printer(mem_ctx,
3634                                     get_server_info_system(),
3635                                     p->msg_ctx,
3636                                     lp_servicename(snum), &pinfo2);
3637         if (!W_ERROR_IS_OK(result)) {
3638                 return WERR_BADFID;
3639         }
3640
3641         for (i=0; i<option->count; i++) {
3642                 option_type = option->types[i];
3643
3644                 switch (option_type.type) {
3645                 case PRINTER_NOTIFY_TYPE:
3646                         if (construct_notify_printer_info(p->msg_ctx,
3647                                                           Printer, info,
3648                                                           pinfo2, snum,
3649                                                           &option_type, id,
3650                                                           mem_ctx)) {
3651                                 id--;
3652                         }
3653                         break;
3654
3655                 case JOB_NOTIFY_TYPE:
3656
3657                         count = print_queue_status(p->msg_ctx, snum, &queue,
3658                                                    &status);
3659
3660                         for (j=0; j<count; j++) {
3661                                 construct_notify_jobs_info(p->msg_ctx,
3662                                                            &queue[j], info,
3663                                                            pinfo2, snum,
3664                                                            &option_type,
3665                                                            queue[j].job,
3666                                                            mem_ctx);
3667                         }
3668
3669                         SAFE_FREE(queue);
3670                         break;
3671                 }
3672         }
3673
3674         /*
3675          * Debugging information, don't delete.
3676          */
3677         /*
3678         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3679         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3680         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3681
3682         for (i=0; i<info->count; i++) {
3683                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3684                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3685                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3686         }
3687         */
3688
3689         talloc_free(pinfo2);
3690         return WERR_OK;
3691 }
3692
3693 /****************************************************************
3694  _spoolss_RouterRefreshPrinterChangeNotify
3695 ****************************************************************/
3696
3697 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3698                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3699 {
3700         struct spoolss_NotifyInfo *info;
3701
3702         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3703         WERROR result = WERR_BADFID;
3704
3705         /* we always have a spoolss_NotifyInfo struct */
3706         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3707         if (!info) {
3708                 result = WERR_NOMEM;
3709                 goto done;
3710         }
3711
3712         *r->out.info = info;
3713
3714         if (!Printer) {
3715                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3716                         "Invalid handle (%s:%u:%u).\n",
3717                         OUR_HANDLE(r->in.handle)));
3718                 goto done;
3719         }
3720
3721         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3722
3723         /*
3724          *      We are now using the change value, and
3725          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3726          *      I don't have a global notification system, I'm sending back all the
3727          *      informations even when _NOTHING_ has changed.
3728          */
3729
3730         /* We need to keep track of the change value to send back in
3731            RRPCN replies otherwise our updates are ignored. */
3732
3733         Printer->notify.fnpcn = true;
3734
3735         if (Printer->notify.cli_chan != NULL &&
3736             Printer->notify.cli_chan->active_connections > 0) {
3737                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3738                         "Saving change value in request [%x]\n",
3739                         r->in.change_low));
3740                 Printer->notify.change = r->in.change_low;
3741         }
3742
3743         /* just ignore the spoolss_NotifyOption */
3744
3745         switch (Printer->printer_type) {
3746                 case SPLHND_SERVER:
3747                         result = printserver_notify_info(p, r->in.handle,
3748                                                          info, p->mem_ctx);
3749                         break;
3750
3751                 case SPLHND_PRINTER:
3752                         result = printer_notify_info(p, r->in.handle,
3753                                                      info, p->mem_ctx);
3754                         break;
3755         }
3756
3757         Printer->notify.fnpcn = false;
3758
3759 done:
3760         return result;
3761 }
3762
3763 /********************************************************************
3764  ********************************************************************/
3765
3766 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3767                                  const char *servername,
3768                                  const char *printername,
3769                                  const char **printername_p)
3770 {
3771         /* FIXME: add lp_force_printername() */
3772
3773         if (servername == NULL) {
3774                 *printername_p = talloc_strdup(mem_ctx, printername);
3775                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3776                 return WERR_OK;
3777         }
3778
3779         if (servername[0] == '\\' && servername[1] == '\\') {
3780                 servername += 2;
3781         }
3782
3783         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3784         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3785
3786         return WERR_OK;
3787 }
3788
3789 /********************************************************************
3790  ********************************************************************/
3791
3792 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3793                                           const char *printername)
3794 {
3795         if (dm == NULL) {
3796                 return;
3797         }
3798
3799         dm->devicename = talloc_strndup(dm, printername,
3800                                         MIN(strlen(printername), 31));
3801 }
3802
3803 /********************************************************************
3804  * construct_printer_info_0
3805  * fill a printer_info_0 struct
3806  ********************************************************************/
3807
3808 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3809                                       const struct auth_serversupplied_info *server_info,
3810                                       struct messaging_context *msg_ctx,
3811                                       struct spoolss_PrinterInfo2 *info2,
3812                                       const char *servername,
3813                                       struct spoolss_PrinterInfo0 *r,
3814                                       int snum)
3815 {
3816         int count;
3817         struct printer_session_counter *session_counter;
3818         struct timeval setuptime;
3819         print_status_struct status;
3820         WERROR result;
3821
3822         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3823         if (!W_ERROR_IS_OK(result)) {
3824                 return result;
3825         }
3826
3827         if (servername) {
3828                 r->servername = talloc_strdup(mem_ctx, servername);
3829                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3830         } else {
3831                 r->servername = NULL;
3832         }
3833
3834         count = print_queue_length(msg_ctx, snum, &status);
3835
3836         /* check if we already have a counter for this printer */
3837         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3838                 if (session_counter->snum == snum)
3839                         break;
3840         }
3841
3842         /* it's the first time, add it to the list */
3843         if (session_counter == NULL) {
3844                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3845                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3846                 session_counter->snum           = snum;
3847                 session_counter->counter        = 0;
3848                 DLIST_ADD(counter_list, session_counter);
3849         }
3850
3851         /* increment it */
3852         session_counter->counter++;
3853
3854         r->cjobs                        = count;
3855         r->total_jobs                   = 0;
3856         r->total_bytes                  = 0;
3857
3858         get_startup_time(&setuptime);
3859         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3860
3861         /* JFM:
3862          * the global_counter should be stored in a TDB as it's common to all the clients
3863          * and should be zeroed on samba startup
3864          */
3865         r->global_counter               = session_counter->counter;
3866         r->total_pages                  = 0;
3867         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3868         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3869         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3870         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3871         r->spooling                     = 0;
3872         r->max_spooling                 = 0;
3873         r->session_counter              = session_counter->counter;
3874         r->num_error_out_of_paper       = 0x0;
3875         r->num_error_not_ready          = 0x0;          /* number of print failure */
3876         r->job_error                    = 0x0;
3877         r->number_of_processors         = 0x1;
3878         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3879         r->high_part_total_bytes        = 0x0;
3880
3881         /* ChangeID in milliseconds*/
3882         winreg_printer_get_changeid(mem_ctx, server_info, msg_ctx,
3883                                     info2->sharename, &r->change_id);
3884
3885         r->last_error                   = WERR_OK;
3886         r->status                       = nt_printq_status(status.status);
3887         r->enumerate_network_printers   = 0x0;
3888         r->c_setprinter                 = 0x0;
3889         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3890         r->processor_level              = 0x6;          /* 6  ???*/
3891         r->ref_ic                       = 0;
3892         r->reserved2                    = 0;
3893         r->reserved3                    = 0;
3894
3895         return WERR_OK;
3896 }
3897
3898
3899 /********************************************************************
3900  * construct_printer_info1
3901  * fill a spoolss_PrinterInfo1 struct
3902 ********************************************************************/
3903
3904 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3905                                       const struct spoolss_PrinterInfo2 *info2,
3906                                       uint32_t flags,
3907                                       const char *servername,
3908                                       struct spoolss_PrinterInfo1 *r,
3909                                       int snum)
3910 {
3911         WERROR result;
3912
3913         r->flags                = flags;
3914
3915         if (info2->comment == NULL || info2->comment[0] == '\0') {
3916                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3917         } else {
3918                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3919         }
3920         W_ERROR_HAVE_NO_MEMORY(r->comment);
3921
3922         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3923         if (!W_ERROR_IS_OK(result)) {
3924                 return result;
3925         }
3926
3927         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3928                                                   r->name,
3929                                                   info2->drivername,
3930                                                   r->comment);
3931         W_ERROR_HAVE_NO_MEMORY(r->description);
3932
3933         return WERR_OK;
3934 }
3935
3936 /********************************************************************
3937  * construct_printer_info2
3938  * fill a spoolss_PrinterInfo2 struct
3939 ********************************************************************/
3940
3941 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3942                                       struct messaging_context *msg_ctx,
3943                                       const struct spoolss_PrinterInfo2 *info2,
3944                                       const char *servername,
3945                                       struct spoolss_PrinterInfo2 *r,
3946                                       int snum)
3947 {
3948         int count;
3949         print_status_struct status;
3950         WERROR result;
3951
3952         count = print_queue_length(msg_ctx, snum, &status);
3953
3954         if (servername) {
3955                 r->servername           = talloc_strdup(mem_ctx, servername);
3956                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3957         } else {
3958                 r->servername           = NULL;
3959         }
3960
3961         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3962         if (!W_ERROR_IS_OK(result)) {
3963                 return result;
3964         }
3965
3966         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3967         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3968         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3969         W_ERROR_HAVE_NO_MEMORY(r->portname);
3970         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3971         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3972
3973         if (info2->comment[0] == '\0') {
3974                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3975         } else {
3976                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3977         }
3978         W_ERROR_HAVE_NO_MEMORY(r->comment);
3979
3980         r->location             = talloc_strdup(mem_ctx, info2->location);
3981         W_ERROR_HAVE_NO_MEMORY(r->location);
3982         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
3983         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3984         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
3985         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3986         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
3987         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3988         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
3989         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3990
3991         r->attributes           = info2->attributes;
3992
3993         r->priority             = info2->priority;
3994         r->defaultpriority      = info2->defaultpriority;
3995         r->starttime            = info2->starttime;
3996         r->untiltime            = info2->untiltime;
3997         r->status               = nt_printq_status(status.status);
3998         r->cjobs                = count;
3999         r->averageppm           = info2->averageppm;
4000
4001         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4002         if (!r->devmode) {
4003                 DEBUG(8,("Returning NULL Devicemode!\n"));
4004         }
4005
4006         compose_devicemode_devicename(r->devmode, r->printername);
4007
4008         r->secdesc = NULL;
4009
4010         if (info2->secdesc != NULL) {
4011                 /* don't use talloc_steal() here unless you do a deep steal of all
4012                    the SEC_DESC members */
4013
4014                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4015         }
4016
4017         return WERR_OK;
4018 }
4019
4020 /********************************************************************
4021  * construct_printer_info3
4022  * fill a spoolss_PrinterInfo3 struct
4023  ********************************************************************/
4024
4025 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4026                                       const struct spoolss_PrinterInfo2 *info2,
4027                                       const char *servername,
4028                                       struct spoolss_PrinterInfo3 *r,
4029                                       int snum)
4030 {
4031         /* These are the components of the SD we are returning. */
4032
4033         if (info2->secdesc != NULL) {
4034                 /* don't use talloc_steal() here unless you do a deep steal of all
4035                    the SEC_DESC members */
4036
4037                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4038                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4039         }
4040
4041         return WERR_OK;
4042 }
4043
4044 /********************************************************************
4045  * construct_printer_info4
4046  * fill a spoolss_PrinterInfo4 struct
4047  ********************************************************************/
4048
4049 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4050                                       const struct spoolss_PrinterInfo2 *info2,
4051                                       const char *servername,
4052                                       struct spoolss_PrinterInfo4 *r,
4053                                       int snum)
4054 {
4055         WERROR result;
4056
4057         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4058         if (!W_ERROR_IS_OK(result)) {
4059                 return result;
4060         }
4061
4062         if (servername) {
4063                 r->servername   = talloc_strdup(mem_ctx, servername);
4064                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4065         } else {
4066                 r->servername = NULL;
4067         }
4068
4069         r->attributes   = info2->attributes;
4070
4071         return WERR_OK;
4072 }
4073
4074 /********************************************************************
4075  * construct_printer_info5
4076  * fill a spoolss_PrinterInfo5 struct
4077  ********************************************************************/
4078
4079 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4080                                       const struct spoolss_PrinterInfo2 *info2,
4081                                       const char *servername,
4082                                       struct spoolss_PrinterInfo5 *r,
4083                                       int snum)
4084 {
4085         WERROR result;
4086
4087         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4088         if (!W_ERROR_IS_OK(result)) {
4089                 return result;
4090         }
4091
4092         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4093         W_ERROR_HAVE_NO_MEMORY(r->portname);
4094
4095         r->attributes   = info2->attributes;
4096
4097         /* these two are not used by NT+ according to MSDN */
4098         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4099         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4100
4101         return WERR_OK;
4102 }
4103
4104 /********************************************************************
4105  * construct_printer_info_6
4106  * fill a spoolss_PrinterInfo6 struct
4107  ********************************************************************/
4108
4109 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4110                                       struct messaging_context *msg_ctx,
4111                                       const struct spoolss_PrinterInfo2 *info2,
4112                                       const char *servername,
4113                                       struct spoolss_PrinterInfo6 *r,
4114                                       int snum)
4115 {
4116         int count;
4117         print_status_struct status;
4118
4119         count = print_queue_length(msg_ctx, snum, &status);
4120
4121         r->status = nt_printq_status(status.status);
4122
4123         return WERR_OK;
4124 }
4125
4126 /********************************************************************
4127  * construct_printer_info7
4128  * fill a spoolss_PrinterInfo7 struct
4129  ********************************************************************/
4130
4131 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4132                                       struct messaging_context *msg_ctx,
4133                                       const char *servername,
4134                                       struct spoolss_PrinterInfo7 *r,
4135                                       int snum)
4136 {
4137         struct auth_serversupplied_info *server_info;
4138         struct GUID guid;
4139         NTSTATUS status;
4140
4141         status = make_server_info_system(mem_ctx, &server_info);
4142         if (!NT_STATUS_IS_OK(status)) {
4143                 DEBUG(0, ("construct_printer_info7: "
4144                           "Could not create system server_info\n"));
4145                 return WERR_NOMEM;
4146         }
4147
4148         if (is_printer_published(mem_ctx, server_info, msg_ctx,
4149                                  servername,
4150                                  lp_servicename(snum), &guid, NULL)) {
4151                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4152                 r->action = DSPRINT_PUBLISH;
4153         } else {
4154                 r->guid = talloc_strdup(mem_ctx, "");
4155                 r->action = DSPRINT_UNPUBLISH;
4156         }
4157         W_ERROR_HAVE_NO_MEMORY(r->guid);
4158
4159         TALLOC_FREE(server_info);
4160         return WERR_OK;
4161 }
4162
4163 /********************************************************************
4164  * construct_printer_info8
4165  * fill a spoolss_PrinterInfo8 struct
4166  ********************************************************************/
4167
4168 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4169                                       const struct spoolss_PrinterInfo2 *info2,
4170                                       const char *servername,
4171                                       struct spoolss_DeviceModeInfo *r,
4172                                       int snum)
4173 {
4174         WERROR result;
4175         const char *printername;
4176
4177         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4178         if (!W_ERROR_IS_OK(result)) {
4179                 return result;
4180         }
4181
4182         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4183         if (!r->devmode) {
4184                 DEBUG(8,("Returning NULL Devicemode!\n"));
4185         }
4186
4187         compose_devicemode_devicename(r->devmode, printername);
4188
4189         return WERR_OK;
4190 }
4191
4192
4193 /********************************************************************
4194 ********************************************************************/
4195
4196 static bool snum_is_shared_printer(int snum)
4197 {
4198         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4199 }
4200
4201 /********************************************************************
4202  Spoolss_enumprinters.
4203 ********************************************************************/
4204
4205 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4206                                            const struct auth_serversupplied_info *server_info,
4207                                            struct messaging_context *msg_ctx,
4208                                            const char *servername,
4209                                            uint32_t level,
4210                                            uint32_t flags,
4211                                            union spoolss_PrinterInfo **info_p,
4212                                            uint32_t *count_p)
4213 {
4214         int snum;
4215         int n_services = lp_numservices();
4216         union spoolss_PrinterInfo *info = NULL;
4217         uint32_t count = 0;
4218         WERROR result = WERR_OK;
4219
4220         *count_p = 0;
4221         *info_p = NULL;
4222
4223         for (snum = 0; snum < n_services; snum++) {
4224
4225                 const char *printer;
4226                 struct spoolss_PrinterInfo2 *info2;
4227
4228                 if (!snum_is_shared_printer(snum)) {
4229                         continue;
4230                 }
4231
4232                 printer = lp_const_servicename(snum);
4233
4234                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4235                         printer, snum));
4236
4237                 result = winreg_create_printer(mem_ctx,
4238                                                server_info,
4239                                                msg_ctx,
4240                                                printer);
4241                 if (!W_ERROR_IS_OK(result)) {
4242                         goto out;
4243                 }
4244
4245                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4246                                             union spoolss_PrinterInfo,
4247                                             count + 1);
4248                 if (!info) {
4249                         result = WERR_NOMEM;
4250                         goto out;
4251                 }
4252
4253                 result = winreg_get_printer(mem_ctx, server_info, msg_ctx,
4254                                             printer, &info2);
4255                 if (!W_ERROR_IS_OK(result)) {
4256                         goto out;
4257                 }
4258
4259                 switch (level) {
4260                 case 0:
4261                         result = construct_printer_info0(info, server_info,
4262                                                          msg_ctx, info2,
4263                                                          servername,
4264                                                          &info[count].info0, snum);
4265                         break;
4266                 case 1:
4267                         result = construct_printer_info1(info, info2, flags,
4268                                                          servername,
4269                                                          &info[count].info1, snum);
4270                         break;
4271                 case 2:
4272                         result = construct_printer_info2(info, msg_ctx, info2,
4273                                                          servername,
4274                                                          &info[count].info2, snum);
4275                         break;
4276                 case 4:
4277                         result = construct_printer_info4(info, info2,
4278                                                          servername,
4279                                                          &info[count].info4, snum);
4280                         break;
4281                 case 5:
4282                         result = construct_printer_info5(info, info2,
4283                                                          servername,
4284                                                          &info[count].info5, snum);
4285                         break;
4286
4287                 default:
4288                         result = WERR_UNKNOWN_LEVEL;
4289                         goto out;
4290                 }
4291
4292                 if (!W_ERROR_IS_OK(result)) {
4293                         goto out;
4294                 }
4295
4296                 count++;
4297         }
4298
4299         *count_p = count;
4300         *info_p = info;
4301
4302  out:
4303         if (!W_ERROR_IS_OK(result)) {
4304                 TALLOC_FREE(info);
4305                 return result;
4306         }
4307
4308         *info_p = info;
4309
4310         return WERR_OK;
4311 }
4312
4313 /********************************************************************
4314  * handle enumeration of printers at level 0
4315  ********************************************************************/
4316
4317 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4318                                   const struct auth_serversupplied_info *server_info,
4319                                   struct messaging_context *msg_ctx,
4320                                   uint32_t flags,
4321                                   const char *servername,
4322                                   union spoolss_PrinterInfo **info,
4323                                   uint32_t *count)
4324 {
4325         DEBUG(4,("enum_all_printers_info_0\n"));
4326
4327         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4328                                             servername, 0, flags, info, count);
4329 }
4330
4331
4332 /********************************************************************
4333 ********************************************************************/
4334
4335 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4336                                        const struct auth_serversupplied_info *server_info,
4337                                        struct messaging_context *msg_ctx,
4338                                        const char *servername,
4339                                        uint32_t flags,
4340                                        union spoolss_PrinterInfo **info,
4341                                        uint32_t *count)
4342 {
4343         DEBUG(4,("enum_all_printers_info_1\n"));
4344
4345         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4346                                             servername, 1, flags, info, count);
4347 }
4348
4349 /********************************************************************
4350  enum_all_printers_info_1_local.
4351 *********************************************************************/
4352
4353 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4354                                              const struct auth_serversupplied_info *server_info,
4355                                              struct messaging_context *msg_ctx,
4356                                              const char *servername,
4357                                              union spoolss_PrinterInfo **info,
4358                                              uint32_t *count)
4359 {
4360         DEBUG(4,("enum_all_printers_info_1_local\n"));
4361
4362         return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4363                                         servername, PRINTER_ENUM_ICON8, info, count);
4364 }
4365
4366 /********************************************************************
4367  enum_all_printers_info_1_name.
4368 *********************************************************************/
4369
4370 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4371                                             const struct auth_serversupplied_info *server_info,
4372                                             struct messaging_context *msg_ctx,
4373                                             const char *servername,
4374                                             union spoolss_PrinterInfo **info,
4375                                             uint32_t *count)
4376 {
4377         const char *s = servername;
4378
4379         DEBUG(4,("enum_all_printers_info_1_name\n"));
4380
4381         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4382                 s = servername + 2;
4383         }
4384
4385         if (!is_myname_or_ipaddr(s)) {
4386                 return WERR_INVALID_NAME;
4387         }
4388
4389         return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4390                                         servername, PRINTER_ENUM_ICON8, info, count);
4391 }
4392
4393 /********************************************************************
4394  enum_all_printers_info_1_network.
4395 *********************************************************************/
4396
4397 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4398                                                const struct auth_serversupplied_info *server_info,
4399                                                struct messaging_context *msg_ctx,
4400                                                const char *servername,
4401                                                union spoolss_PrinterInfo **info,
4402                                                uint32_t *count)
4403 {
4404         const char *s = servername;
4405
4406         DEBUG(4,("enum_all_printers_info_1_network\n"));
4407
4408         /* If we respond to a enum_printers level 1 on our name with flags
4409            set to PRINTER_ENUM_REMOTE with a list of printers then these
4410            printers incorrectly appear in the APW browse list.
4411            Specifically the printers for the server appear at the workgroup
4412            level where all the other servers in the domain are
4413            listed. Windows responds to this call with a
4414            WERR_CAN_NOT_COMPLETE so we should do the same. */
4415
4416         if (servername[0] == '\\' && servername[1] == '\\') {
4417                  s = servername + 2;
4418         }
4419
4420         if (is_myname_or_ipaddr(s)) {
4421                  return WERR_CAN_NOT_COMPLETE;
4422         }
4423
4424         return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4425                                         servername, PRINTER_ENUM_NAME, info, count);
4426 }
4427
4428 /********************************************************************
4429  * api_spoolss_enumprinters
4430  *
4431  * called from api_spoolss_enumprinters (see this to understand)
4432  ********************************************************************/
4433
4434 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4435                                        const struct auth_serversupplied_info *server_info,
4436                                        struct messaging_context *msg_ctx,
4437                                        const char *servername,
4438                                        union spoolss_PrinterInfo **info,
4439                                        uint32_t *count)
4440 {
4441         DEBUG(4,("enum_all_printers_info_2\n"));
4442
4443         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4444                                             servername, 2, 0, info, count);
4445 }
4446
4447 /********************************************************************
4448  * handle enumeration of printers at level 1
4449  ********************************************************************/
4450
4451 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4452                                   const struct auth_serversupplied_info *server_info,
4453                                   struct messaging_context *msg_ctx,
4454                                   uint32_t flags,
4455                                   const char *servername,
4456                                   union spoolss_PrinterInfo **info,
4457                                   uint32_t *count)
4458 {
4459         /* Not all the flags are equals */
4460
4461         if (flags & PRINTER_ENUM_LOCAL) {
4462                 return enum_all_printers_info_1_local(mem_ctx, server_info,
4463                                                       msg_ctx, servername, info, count);
4464         }
4465
4466         if (flags & PRINTER_ENUM_NAME) {
4467                 return enum_all_printers_info_1_name(mem_ctx, server_info,
4468                                                      msg_ctx, servername, info,
4469                                                      count);
4470         }
4471
4472         if (flags & PRINTER_ENUM_NETWORK) {
4473                 return enum_all_printers_info_1_network(mem_ctx, server_info,
4474                                                         msg_ctx, servername, info,
4475                                                         count);
4476         }
4477
4478         return WERR_OK; /* NT4sp5 does that */
4479 }
4480
4481 /********************************************************************
4482  * handle enumeration of printers at level 2
4483  ********************************************************************/
4484
4485 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4486                                   const struct auth_serversupplied_info *server_info,
4487                                   struct messaging_context *msg_ctx,
4488                                   uint32_t flags,
4489                                   const char *servername,
4490                                   union spoolss_PrinterInfo **info,
4491                                   uint32_t *count)
4492 {
4493         if (flags & PRINTER_ENUM_LOCAL) {
4494
4495                 return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
4496                                                 servername,
4497                                                 info, count);
4498         }
4499
4500         if (flags & PRINTER_ENUM_NAME) {
4501                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4502                         return WERR_INVALID_NAME;
4503                 }
4504
4505                 return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
4506                                                 servername,
4507                                                 info, count);
4508         }
4509
4510         if (flags & PRINTER_ENUM_REMOTE) {
4511                 return WERR_UNKNOWN_LEVEL;
4512         }
4513
4514         return WERR_OK;
4515 }
4516
4517 /********************************************************************
4518  * handle enumeration of printers at level 4
4519  ********************************************************************/
4520
4521 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4522                                   const struct auth_serversupplied_info *server_info,
4523                                   struct messaging_context *msg_ctx,
4524                                   uint32_t flags,
4525                                   const char *servername,
4526                                   union spoolss_PrinterInfo **info,
4527                                   uint32_t *count)
4528 {
4529         DEBUG(4,("enum_all_printers_info_4\n"));
4530
4531         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4532                                             servername, 4, flags, info, count);
4533 }
4534
4535
4536 /********************************************************************
4537  * handle enumeration of printers at level 5
4538  ********************************************************************/
4539
4540 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4541                                   const struct auth_serversupplied_info *server_info,
4542                                   struct messaging_context *msg_ctx,
4543                                   uint32_t flags,
4544                                   const char *servername,
4545                                   union spoolss_PrinterInfo **info,
4546                                   uint32_t *count)
4547 {
4548         DEBUG(4,("enum_all_printers_info_5\n"));
4549
4550         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4551                                             servername, 5, flags, info, count);
4552 }
4553
4554 /****************************************************************
4555  _spoolss_EnumPrinters
4556 ****************************************************************/
4557
4558 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4559                              struct spoolss_EnumPrinters *r)
4560 {
4561         const struct auth_serversupplied_info *server_info = get_server_info_system();
4562         WERROR result;
4563
4564         /* that's an [in out] buffer */
4565
4566         if (!r->in.buffer && (r->in.offered != 0)) {
4567                 return WERR_INVALID_PARAM;
4568         }
4569
4570         DEBUG(4,("_spoolss_EnumPrinters\n"));
4571
4572         *r->out.needed = 0;
4573         *r->out.count = 0;
4574         *r->out.info = NULL;
4575
4576         /*
4577          * Level 1:
4578          *          flags==PRINTER_ENUM_NAME
4579          *           if name=="" then enumerates all printers
4580          *           if name!="" then enumerate the printer
4581          *          flags==PRINTER_ENUM_REMOTE
4582          *          name is NULL, enumerate printers
4583          * Level 2: name!="" enumerates printers, name can't be NULL
4584          * Level 3: doesn't exist
4585          * Level 4: does a local registry lookup
4586          * Level 5: same as Level 2
4587          */
4588
4589         if (r->in.server && r->in.server[0] == '\0') {
4590                 r->in.server = NULL;
4591         }
4592
4593         switch (r->in.level) {
4594         case 0:
4595                 result = enumprinters_level0(p->mem_ctx, server_info,
4596                                              p->msg_ctx, r->in.flags,
4597                                              r->in.server,
4598                                              r->out.info, r->out.count);
4599                 break;
4600         case 1:
4601                 result = enumprinters_level1(p->mem_ctx, server_info,
4602                                              p->msg_ctx, r->in.flags,
4603                                              r->in.server,
4604                                              r->out.info, r->out.count);
4605                 break;
4606         case 2:
4607                 result = enumprinters_level2(p->mem_ctx, server_info,
4608                                              p->msg_ctx, r->in.flags,
4609                                              r->in.server,
4610                                              r->out.info, r->out.count);
4611                 break;
4612         case 4:
4613                 result = enumprinters_level4(p->mem_ctx, server_info,
4614                                              p->msg_ctx, r->in.flags,
4615                                              r->in.server,
4616                                              r->out.info, r->out.count);
4617                 break;
4618         case 5:
4619                 result = enumprinters_level5(p->mem_ctx, server_info,
4620                                              p->msg_ctx, r->in.flags,
4621                                              r->in.server,
4622                                              r->out.info, r->out.count);
4623                 break;
4624         default:
4625                 return WERR_UNKNOWN_LEVEL;
4626         }
4627
4628         if (!W_ERROR_IS_OK(result)) {
4629                 return result;
4630         }
4631
4632         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4633                                                      spoolss_EnumPrinters, 
4634                                                      *r->out.info, r->in.level,
4635                                                      *r->out.count);
4636         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4637         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4638
4639         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4640 }
4641
4642 /****************************************************************
4643  _spoolss_GetPrinter
4644 ****************************************************************/
4645
4646 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4647                            struct spoolss_GetPrinter *r)
4648 {
4649         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4650         struct spoolss_PrinterInfo2 *info2 = NULL;
4651         WERROR result = WERR_OK;
4652         int snum;
4653
4654         /* that's an [in out] buffer */
4655
4656         if (!r->in.buffer && (r->in.offered != 0)) {
4657                 return WERR_INVALID_PARAM;
4658         }
4659
4660         *r->out.needed = 0;
4661
4662         if (Printer == NULL) {
4663                 return WERR_BADFID;
4664         }
4665
4666         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4667                 return WERR_BADFID;
4668         }
4669
4670         result = winreg_get_printer(p->mem_ctx,
4671                                     get_server_info_system(),
4672                                     p->msg_ctx,
4673                                     lp_const_servicename(snum),
4674                                     &info2);
4675         if (!W_ERROR_IS_OK(result)) {
4676                 goto out;
4677         }
4678
4679         switch (r->in.level) {
4680         case 0:
4681                 result = construct_printer_info0(p->mem_ctx,
4682                                                  get_server_info_system(),
4683                                                  p->msg_ctx,
4684                                                  info2,
4685                                                  Printer->servername,
4686                                                  &r->out.info->info0,
4687                                                  snum);
4688                 break;
4689         case 1:
4690                 result = construct_printer_info1(p->mem_ctx, info2,
4691                                                  PRINTER_ENUM_ICON8,
4692                                                  Printer->servername,
4693                                                  &r->out.info->info1, snum);
4694                 break;
4695         case 2:
4696                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4697                                                  Printer->servername,
4698                                                  &r->out.info->info2, snum);
4699                 break;
4700         case 3:
4701                 result = construct_printer_info3(p->mem_ctx, info2,
4702                                                  Printer->servername,
4703                                                  &r->out.info->info3, snum);
4704                 break;
4705         case 4:
4706                 result = construct_printer_info4(p->mem_ctx, info2,
4707                                                  Printer->servername,
4708                                                  &r->out.info->info4, snum);
4709                 break;
4710         case 5:
4711                 result = construct_printer_info5(p->mem_ctx, info2,
4712                                                  Printer->servername,
4713                                                  &r->out.info->info5, snum);
4714                 break;
4715         case 6:
4716                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4717                                                  Printer->servername,
4718                                                  &r->out.info->info6, snum);
4719                 break;
4720         case 7:
4721                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4722                                                  Printer->servername,
4723                                                  &r->out.info->info7, snum);
4724                 break;
4725         case 8:
4726                 result = construct_printer_info8(p->mem_ctx, info2,
4727                                                  Printer->servername,
4728                                                  &r->out.info->info8, snum);
4729                 break;
4730         default:
4731                 result = WERR_UNKNOWN_LEVEL;
4732                 break;
4733         }
4734
4735  out:
4736         if (!W_ERROR_IS_OK(result)) {
4737                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4738                           r->in.level, win_errstr(result)));
4739                 TALLOC_FREE(r->out.info);
4740                 return result;
4741         }
4742
4743         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, 
4744                                                r->out.info, r->in.level);
4745         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4746
4747         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4748 }
4749
4750 /********************************************************************
4751  ********************************************************************/
4752
4753 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4754         do { \
4755                 if (in && strlen(in)) { \
4756                         out = talloc_strdup(mem_ctx, in); \
4757                 } else { \
4758                         out = talloc_strdup(mem_ctx, ""); \
4759                 } \
4760                 W_ERROR_HAVE_NO_MEMORY(out); \
4761         } while (0);
4762
4763 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4764         do { \
4765                 if (in && strlen(in)) { \
4766                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4767                 } else { \
4768                         out = talloc_strdup(mem_ctx, ""); \
4769                 } \
4770                 W_ERROR_HAVE_NO_MEMORY(out); \
4771         } while (0);
4772
4773 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4774                                                   const char **string_array,
4775                                                   const char ***presult,
4776                                                   const char *cservername,
4777                                                   const char *arch,
4778                                                   int version)
4779 {
4780         int i, num_strings = 0;
4781         const char **array = NULL;
4782
4783         if (string_array == NULL) {
4784                 return WERR_INVALID_PARAMETER;;
4785         }
4786
4787         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4788                 const char *str = NULL;
4789
4790                 if (cservername == NULL || arch == NULL) {
4791                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4792                 } else {
4793                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4794                 }
4795
4796                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4797                         TALLOC_FREE(array);
4798                         return WERR_NOMEM;
4799                 }
4800         }
4801
4802         if (i > 0) {
4803                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4804                              &array, &num_strings);
4805         }
4806
4807         if (presult) {
4808                 *presult = array;
4809         }
4810
4811         return WERR_OK;
4812 }
4813
4814 /********************************************************************
4815  * fill a spoolss_DriverInfo1 struct
4816  ********************************************************************/
4817
4818 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4819                                         struct spoolss_DriverInfo1 *r,
4820                                         const struct spoolss_DriverInfo8 *driver,
4821                                         const char *servername)
4822 {
4823         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4824         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4825
4826         return WERR_OK;
4827 }
4828
4829 /********************************************************************
4830  * fill a spoolss_DriverInfo2 struct
4831  ********************************************************************/
4832
4833 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4834                                         struct spoolss_DriverInfo2 *r,
4835                                         const struct spoolss_DriverInfo8 *driver,
4836                                         const char *servername)
4837
4838 {
4839         const char *cservername = canon_servername(servername);
4840
4841         r->version              = driver->version;
4842
4843         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4844         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4845         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4846         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4847
4848         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4849                                driver->architecture,
4850                                driver->version,
4851                                driver->driver_path,
4852                                r->driver_path);
4853
4854         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4855                                driver->architecture,
4856                                driver->version,
4857                                driver->data_file,
4858                                r->data_file);
4859
4860         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4861                                driver->architecture,
4862                                driver->version,
4863                                driver->config_file,
4864                                r->config_file);
4865
4866         return WERR_OK;
4867 }
4868
4869 /********************************************************************
4870  * fill a spoolss_DriverInfo3 struct
4871  ********************************************************************/
4872
4873 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4874                                         struct spoolss_DriverInfo3 *r,
4875                                         const struct spoolss_DriverInfo8 *driver,
4876                                         const char *servername)
4877 {
4878         const char *cservername = canon_servername(servername);
4879
4880         r->version              = driver->version;
4881
4882         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4883         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4884         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4885         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4886
4887         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4888                                driver->architecture,
4889                                driver->version,
4890                                driver->driver_path,
4891                                r->driver_path);
4892
4893         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4894                                driver->architecture,
4895                                driver->version,
4896                                driver->data_file,
4897                                r->data_file);
4898
4899         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4900                                driver->architecture,
4901                                driver->version,
4902                                driver->config_file,
4903                                r->config_file);
4904
4905         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4906                                driver->architecture,
4907                                driver->version,
4908                                driver->help_file,
4909                                r->help_file);
4910
4911         FILL_DRIVER_STRING(mem_ctx,
4912                            driver->monitor_name,
4913                            r->monitor_name);
4914
4915         FILL_DRIVER_STRING(mem_ctx,
4916                            driver->default_datatype,
4917                            r->default_datatype);
4918
4919         return string_array_from_driver_info(mem_ctx,
4920                                              driver->dependent_files,
4921                                              &r->dependent_files,
4922                                              cservername,
4923                                              driver->architecture,
4924                                              driver->version);
4925 }
4926
4927 /********************************************************************
4928  * fill a spoolss_DriverInfo4 struct
4929  ********************************************************************/
4930
4931 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4932                                         struct spoolss_DriverInfo4 *r,
4933                                         const struct spoolss_DriverInfo8 *driver,
4934                                         const char *servername)
4935 {
4936         const char *cservername = canon_servername(servername);
4937         WERROR result;
4938
4939         r->version              = driver->version;
4940
4941         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4942         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4943         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4944         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4945
4946         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4947                                driver->architecture,
4948                                driver->version,
4949                                driver->driver_path,
4950                                r->driver_path);
4951
4952         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4953                                driver->architecture,
4954                                driver->version,
4955                                driver->data_file,
4956                                r->data_file);
4957
4958         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4959                                driver->architecture,
4960                                driver->version,
4961                                driver->config_file,
4962                                r->config_file);
4963
4964         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4965                                driver->architecture,
4966                                driver->version,
4967                                driver->help_file,
4968                                r->help_file);
4969
4970         result = string_array_from_driver_info(mem_ctx,
4971                                                driver->dependent_files,
4972                                                &r->dependent_files,
4973                                                cservername,
4974                                                driver->architecture,
4975                                                driver->version);
4976         if (!W_ERROR_IS_OK(result)) {
4977                 return result;
4978         }
4979
4980         FILL_DRIVER_STRING(mem_ctx,
4981                            driver->monitor_name,
4982                            r->monitor_name);
4983
4984         FILL_DRIVER_STRING(mem_ctx,
4985                            driver->default_datatype,
4986                            r->default_datatype);
4987
4988
4989         result = string_array_from_driver_info(mem_ctx,
4990                                                driver->previous_names,
4991                                                &r->previous_names,
4992                                                NULL, NULL, 0);
4993
4994         return result;
4995 }
4996
4997 /********************************************************************
4998  * fill a spoolss_DriverInfo5 struct
4999  ********************************************************************/
5000
5001 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5002                                         struct spoolss_DriverInfo5 *r,
5003                                         const struct spoolss_DriverInfo8 *driver,
5004                                         const char *servername)
5005 {
5006         const char *cservername = canon_servername(servername);
5007
5008         r->version              = driver->version;
5009
5010         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5011         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5012         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5013         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5014
5015         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5016                                driver->architecture,
5017                                driver->version,
5018                                driver->driver_path,
5019                                r->driver_path);
5020
5021         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5022                                driver->architecture,
5023                                driver->version,
5024                                driver->data_file,
5025                                r->data_file);
5026
5027         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5028                                driver->architecture,
5029                                driver->version,
5030                                driver->config_file,
5031                                r->config_file);
5032
5033         r->driver_attributes    = 0;
5034         r->config_version       = 0;
5035         r->driver_version       = 0;
5036
5037         return WERR_OK;
5038 }
5039 /********************************************************************
5040  * fill a spoolss_DriverInfo6 struct
5041  ********************************************************************/
5042
5043 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5044                                         struct spoolss_DriverInfo6 *r,
5045                                         const struct spoolss_DriverInfo8 *driver,
5046                                         const char *servername)
5047 {
5048         const char *cservername = canon_servername(servername);
5049         WERROR result;
5050
5051         r->version              = driver->version;
5052
5053         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5054         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5055         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5056         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5057
5058         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5059                                driver->architecture,
5060                                driver->version,
5061                                driver->driver_path,
5062                                r->driver_path);
5063
5064         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5065                                driver->architecture,
5066                                driver->version,
5067                                driver->data_file,
5068                                r->data_file);
5069
5070         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5071                                driver->architecture,
5072                                driver->version,
5073                                driver->config_file,
5074                                r->config_file);
5075
5076         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5077                                driver->architecture,
5078                                driver->version,
5079                                driver->help_file,
5080                                r->help_file);
5081
5082         FILL_DRIVER_STRING(mem_ctx,
5083                            driver->monitor_name,
5084                            r->monitor_name);
5085
5086         FILL_DRIVER_STRING(mem_ctx,
5087                            driver->default_datatype,
5088                            r->default_datatype);
5089
5090         result = string_array_from_driver_info(mem_ctx,
5091                                                driver->dependent_files,
5092                                                &r->dependent_files,
5093                                                cservername,
5094                                                driver->architecture,
5095                                                driver->version);
5096         if (!W_ERROR_IS_OK(result)) {
5097                 return result;
5098         }
5099
5100         result = string_array_from_driver_info(mem_ctx,
5101                                                driver->previous_names,
5102                                                &r->previous_names,
5103                                                NULL, NULL, 0);
5104         if (!W_ERROR_IS_OK(result)) {
5105                 return result;
5106         }
5107
5108         r->driver_date          = driver->driver_date;
5109         r->driver_version       = driver->driver_version;
5110
5111         FILL_DRIVER_STRING(mem_ctx,
5112                            driver->manufacturer_name,
5113                            r->manufacturer_name);
5114         FILL_DRIVER_STRING(mem_ctx,
5115                            driver->manufacturer_url,
5116                            r->manufacturer_url);
5117         FILL_DRIVER_STRING(mem_ctx,
5118                            driver->hardware_id,
5119                            r->hardware_id);
5120         FILL_DRIVER_STRING(mem_ctx,
5121                            driver->provider,
5122                            r->provider);
5123
5124         return WERR_OK;
5125 }
5126
5127 /********************************************************************
5128  * fill a spoolss_DriverInfo8 struct
5129  ********************************************************************/
5130
5131 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5132                                         struct spoolss_DriverInfo8 *r,
5133                                         const struct spoolss_DriverInfo8 *driver,
5134                                         const char *servername)
5135 {
5136         const char *cservername = canon_servername(servername);
5137         WERROR result;
5138
5139         r->version              = driver->version;
5140
5141         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5142         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5143         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5144         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5145
5146         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5147                                driver->architecture,
5148                                driver->version,
5149                                driver->driver_path,
5150                                r->driver_path);
5151
5152         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5153                                driver->architecture,
5154                                driver->version,
5155                                driver->data_file,
5156                                r->data_file);
5157
5158         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5159                                driver->architecture,
5160                                driver->version,
5161                                driver->config_file,
5162                                r->config_file);
5163
5164         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5165                                driver->architecture,
5166                                driver->version,
5167                                driver->help_file,
5168                                r->help_file);
5169
5170         FILL_DRIVER_STRING(mem_ctx,
5171                            driver->monitor_name,
5172                            r->monitor_name);
5173
5174         FILL_DRIVER_STRING(mem_ctx,
5175                            driver->default_datatype,
5176                            r->default_datatype);
5177
5178         result = string_array_from_driver_info(mem_ctx,
5179                                                driver->dependent_files,
5180                                                &r->dependent_files,
5181                                                cservername,
5182                                                driver->architecture,
5183                                                driver->version);
5184         if (!W_ERROR_IS_OK(result)) {
5185                 return result;
5186         }
5187
5188         result = string_array_from_driver_info(mem_ctx,
5189                                                driver->previous_names,
5190                                                &r->previous_names,
5191                                                NULL, NULL, 0);
5192         if (!W_ERROR_IS_OK(result)) {
5193                 return result;
5194         }
5195
5196         r->driver_date          = driver->driver_date;
5197         r->driver_version       = driver->driver_version;
5198
5199         FILL_DRIVER_STRING(mem_ctx,
5200                            driver->manufacturer_name,
5201                            r->manufacturer_name);
5202         FILL_DRIVER_STRING(mem_ctx,
5203                            driver->manufacturer_url,
5204                            r->manufacturer_url);
5205         FILL_DRIVER_STRING(mem_ctx,
5206                            driver->hardware_id,
5207                            r->hardware_id);
5208         FILL_DRIVER_STRING(mem_ctx,
5209                            driver->provider,
5210                            r->provider);
5211
5212         FILL_DRIVER_STRING(mem_ctx,
5213                            driver->print_processor,
5214                            r->print_processor);
5215         FILL_DRIVER_STRING(mem_ctx,
5216                            driver->vendor_setup,
5217                            r->vendor_setup);
5218
5219         result = string_array_from_driver_info(mem_ctx,
5220                                                driver->color_profiles,
5221                                                &r->color_profiles,
5222                                                NULL, NULL, 0);
5223         if (!W_ERROR_IS_OK(result)) {
5224                 return result;
5225         }
5226
5227         FILL_DRIVER_STRING(mem_ctx,
5228                            driver->inf_path,
5229                            r->inf_path);
5230
5231         r->printer_driver_attributes    = driver->printer_driver_attributes;
5232
5233         result = string_array_from_driver_info(mem_ctx,
5234                                                driver->core_driver_dependencies,
5235                                                &r->core_driver_dependencies,
5236                                                NULL, NULL, 0);
5237         if (!W_ERROR_IS_OK(result)) {
5238                 return result;
5239         }
5240
5241         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5242         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5243
5244         return WERR_OK;
5245 }
5246
5247 #if 0 /* disabled until marshalling issues are resolved - gd */
5248 /********************************************************************
5249  ********************************************************************/
5250
5251 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5252                                           struct spoolss_DriverFileInfo *r,
5253                                           const char *cservername,
5254                                           const char *file_name,
5255                                           enum spoolss_DriverFileType file_type,
5256                                           uint32_t file_version)
5257 {
5258         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5259                                           cservername, file_name);
5260         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5261         r->file_type    = file_type;
5262         r->file_version = file_version;
5263
5264         return WERR_OK;
5265 }
5266
5267 /********************************************************************
5268  ********************************************************************/
5269
5270 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5271                                                  const struct spoolss_DriverInfo8 *driver,
5272                                                  const char *cservername,
5273                                                  struct spoolss_DriverFileInfo **info_p,
5274                                                  uint32_t *count_p)
5275 {
5276         struct spoolss_DriverFileInfo *info = NULL;
5277         uint32_t count = 0;
5278         WERROR result;
5279         uint32_t i;
5280
5281         *info_p = NULL;
5282         *count_p = 0;
5283
5284         if (strlen(driver->driver_path)) {
5285                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5286                                             struct spoolss_DriverFileInfo,
5287                                             count + 1);
5288                 W_ERROR_HAVE_NO_MEMORY(info);
5289                 result = fill_spoolss_DriverFileInfo(info,
5290                                                      &info[count],
5291                                                      cservername,
5292                                                      driver->driver_path,
5293                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5294                                                      0);
5295                 W_ERROR_NOT_OK_RETURN(result);
5296                 count++;
5297         }
5298
5299         if (strlen(driver->config_file)) {
5300                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5301                                             struct spoolss_DriverFileInfo,
5302                                             count + 1);
5303                 W_ERROR_HAVE_NO_MEMORY(info);
5304                 result = fill_spoolss_DriverFileInfo(info,
5305                                                      &info[count],
5306                                                      cservername,
5307                                                      driver->config_file,
5308                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5309                                                      0);
5310                 W_ERROR_NOT_OK_RETURN(result);
5311                 count++;
5312         }
5313
5314         if (strlen(driver->data_file)) {
5315                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5316                                             struct spoolss_DriverFileInfo,
5317                                             count + 1);
5318                 W_ERROR_HAVE_NO_MEMORY(info);
5319                 result = fill_spoolss_DriverFileInfo(info,
5320                                                      &info[count],
5321                                                      cservername,
5322                                                      driver->data_file,
5323                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5324                                                      0);
5325                 W_ERROR_NOT_OK_RETURN(result);
5326                 count++;
5327         }
5328
5329         if (strlen(driver->help_file)) {
5330                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5331                                             struct spoolss_DriverFileInfo,
5332                                             count + 1);
5333                 W_ERROR_HAVE_NO_MEMORY(info);
5334                 result = fill_spoolss_DriverFileInfo(info,
5335                                                      &info[count],
5336                                                      cservername,
5337                                                      driver->help_file,
5338                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5339                                                      0);
5340                 W_ERROR_NOT_OK_RETURN(result);
5341                 count++;
5342         }
5343
5344         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5345                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5346                                             struct spoolss_DriverFileInfo,
5347                                             count + 1);
5348                 W_ERROR_HAVE_NO_MEMORY(info);
5349                 result = fill_spoolss_DriverFileInfo(info,
5350                                                      &info[count],
5351                                                      cservername,
5352                                                      driver->dependent_files[i],
5353                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5354                                                      0);
5355                 W_ERROR_NOT_OK_RETURN(result);
5356                 count++;
5357         }
5358
5359         *info_p = info;
5360         *count_p = count;
5361
5362         return WERR_OK;
5363 }
5364
5365 /********************************************************************
5366  * fill a spoolss_DriverInfo101 struct
5367  ********************************************************************/
5368
5369 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5370                                           struct spoolss_DriverInfo101 *r,
5371                                           const struct spoolss_DriverInfo8 *driver,
5372                                           const char *servername)
5373 {
5374         const char *cservername = canon_servername(servername);
5375         WERROR result;
5376
5377         r->version              = driver->version;
5378
5379         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5380         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5381         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5382         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5383
5384         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5385                                                     cservername,
5386                                                     &r->file_info,
5387                                                     &r->file_count);
5388         if (!W_ERROR_IS_OK(result)) {
5389                 return result;
5390         }
5391
5392         FILL_DRIVER_STRING(mem_ctx,
5393                            driver->monitor_name,
5394                            r->monitor_name);
5395
5396         FILL_DRIVER_STRING(mem_ctx,
5397                            driver->default_datatype,
5398                            r->default_datatype);
5399
5400         result = string_array_from_driver_info(mem_ctx,
5401                                                driver->previous_names,
5402                                                &r->previous_names,
5403                                                NULL, NULL, 0);
5404         if (!W_ERROR_IS_OK(result)) {
5405                 return result;
5406         }
5407
5408         r->driver_date          = driver->driver_date;
5409         r->driver_version       = driver->driver_version;
5410
5411         FILL_DRIVER_STRING(mem_ctx,
5412                            driver->manufacturer_name,
5413                            r->manufacturer_name);
5414         FILL_DRIVER_STRING(mem_ctx,
5415                            driver->manufacturer_url,
5416                            r->manufacturer_url);
5417         FILL_DRIVER_STRING(mem_ctx,
5418                            driver->hardware_id,
5419                            r->hardware_id);
5420         FILL_DRIVER_STRING(mem_ctx,
5421                            driver->provider,
5422                            r->provider);
5423
5424         return WERR_OK;
5425 }
5426 #endif
5427 /********************************************************************
5428  ********************************************************************/
5429
5430 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5431                                                   const struct auth_serversupplied_info *server_info,
5432                                                   struct messaging_context *msg_ctx,
5433                                                   uint32_t level,
5434                                                   union spoolss_DriverInfo *r,
5435                                                   int snum,
5436                                                   const char *servername,
5437                                                   const char *architecture,
5438                                                   uint32_t version)
5439 {
5440         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5441         struct spoolss_DriverInfo8 *driver;
5442         WERROR result;
5443
5444         if (level == 101) {
5445                 return WERR_UNKNOWN_LEVEL;
5446         }
5447
5448         result = winreg_get_printer(mem_ctx,
5449                                     server_info,
5450                                     msg_ctx,
5451                                     lp_const_servicename(snum),
5452                                     &pinfo2);
5453
5454         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5455                 win_errstr(result)));
5456
5457         if (!W_ERROR_IS_OK(result)) {
5458                 return WERR_INVALID_PRINTER_NAME;
5459         }
5460
5461         result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5462                                    architecture,
5463                                    pinfo2->drivername, version, &driver);
5464
5465         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5466                 win_errstr(result)));
5467
5468         if (!W_ERROR_IS_OK(result)) {
5469                 /*
5470                  * Is this a W2k client ?
5471                  */
5472
5473                 if (version < 3) {
5474                         talloc_free(pinfo2);
5475                         return WERR_UNKNOWN_PRINTER_DRIVER;
5476                 }
5477
5478                 /* Yes - try again with a WinNT driver. */
5479                 version = 2;
5480                 result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5481                                            architecture,
5482                                            pinfo2->drivername,
5483                                            version, &driver);
5484                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5485                         win_errstr(result)));
5486                 if (!W_ERROR_IS_OK(result)) {
5487                         talloc_free(pinfo2);
5488                         return WERR_UNKNOWN_PRINTER_DRIVER;
5489                 }
5490         }
5491
5492         switch (level) {
5493         case 1:
5494                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5495                 break;
5496         case 2:
5497                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5498                 break;
5499         case 3:
5500                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5501                 break;
5502         case 4:
5503                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5504                 break;
5505         case 5:
5506                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5507                 break;
5508         case 6:
5509                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5510                 break;
5511         case 8:
5512                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5513                 break;
5514 #if 0 /* disabled until marshalling issues are resolved - gd */
5515         case 101:
5516                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5517                 break;
5518 #endif
5519         default:
5520                 result = WERR_UNKNOWN_LEVEL;
5521                 break;
5522         }
5523
5524         talloc_free(pinfo2);
5525         talloc_free(driver);
5526
5527         return result;
5528 }
5529
5530 /****************************************************************
5531  _spoolss_GetPrinterDriver2
5532 ****************************************************************/
5533
5534 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5535                                   struct spoolss_GetPrinterDriver2 *r)
5536 {
5537         struct printer_handle *printer;
5538         WERROR result;
5539
5540         int snum;
5541
5542         /* that's an [in out] buffer */
5543
5544         if (!r->in.buffer && (r->in.offered != 0)) {
5545                 return WERR_INVALID_PARAM;
5546         }
5547
5548         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5549
5550         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5551                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5552                 return WERR_INVALID_PRINTER_NAME;
5553         }
5554
5555         *r->out.needed = 0;
5556         *r->out.server_major_version = 0;
5557         *r->out.server_minor_version = 0;
5558
5559         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5560                 return WERR_BADFID;
5561         }
5562
5563         result = construct_printer_driver_info_level(p->mem_ctx,
5564                                                      get_server_info_system(),
5565                                                      p->msg_ctx,
5566                                                      r->in.level, r->out.info,
5567                                                      snum, printer->servername,
5568                                                      r->in.architecture,
5569                                                      r->in.client_major_version);
5570         if (!W_ERROR_IS_OK(result)) {
5571                 TALLOC_FREE(r->out.info);
5572                 return result;
5573         }
5574
5575         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, 
5576                                                r->out.info, r->in.level);
5577         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5578
5579         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5580 }
5581
5582
5583 /****************************************************************
5584  _spoolss_StartPagePrinter
5585 ****************************************************************/
5586
5587 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5588                                  struct spoolss_StartPagePrinter *r)
5589 {
5590         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5591
5592         if (!Printer) {
5593                 DEBUG(3,("_spoolss_StartPagePrinter: "
5594                         "Error in startpageprinter printer handle\n"));
5595                 return WERR_BADFID;
5596         }
5597
5598         Printer->page_started = true;
5599         return WERR_OK;
5600 }
5601
5602 /****************************************************************
5603  _spoolss_EndPagePrinter
5604 ****************************************************************/
5605
5606 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5607                                struct spoolss_EndPagePrinter *r)
5608 {
5609         int snum;
5610
5611         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5612
5613         if (!Printer) {
5614                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5615                         OUR_HANDLE(r->in.handle)));
5616                 return WERR_BADFID;
5617         }
5618
5619         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5620                 return WERR_BADFID;
5621
5622         Printer->page_started = false;
5623         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5624
5625         return WERR_OK;
5626 }
5627
5628 /****************************************************************
5629  _spoolss_StartDocPrinter
5630 ****************************************************************/
5631
5632 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5633                                 struct spoolss_StartDocPrinter *r)
5634 {
5635         struct spoolss_DocumentInfo1 *info_1;
5636         int snum;
5637         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5638         WERROR werr;
5639
5640         if (!Printer) {
5641                 DEBUG(2,("_spoolss_StartDocPrinter: "
5642                         "Invalid handle (%s:%u:%u)\n",
5643                         OUR_HANDLE(r->in.handle)));
5644                 return WERR_BADFID;
5645         }
5646
5647         if (Printer->jobid) {
5648                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5649                           "StartDocPrinter called twice! "
5650                           "(existing jobid = %d)\n", Printer->jobid));
5651                 return WERR_INVALID_HANDLE;
5652         }
5653
5654         if (r->in.level != 1) {
5655                 return WERR_UNKNOWN_LEVEL;
5656         }
5657
5658         info_1 = r->in.info.info1;
5659
5660         /*
5661          * a nice thing with NT is it doesn't listen to what you tell it.
5662          * when asked to send _only_ RAW datas, it tries to send datas
5663          * in EMF format.
5664          *
5665          * So I add checks like in NT Server ...
5666          */
5667
5668         if (info_1->datatype) {
5669                 if (strcmp(info_1->datatype, "RAW") != 0) {
5670                         *r->out.job_id = 0;
5671                         return WERR_INVALID_DATATYPE;
5672                 }
5673         }
5674
5675         /* get the share number of the printer */
5676         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5677                 return WERR_BADFID;
5678         }
5679
5680         werr = print_job_start(p->server_info,
5681                                p->msg_ctx,
5682                                p->client_id->name,
5683                                snum,
5684                                info_1->document_name,
5685                                info_1->output_file,
5686                                Printer->devmode,
5687                                &Printer->jobid);
5688
5689         /* An error occured in print_job_start() so return an appropriate
5690            NT error code. */
5691
5692         if (!W_ERROR_IS_OK(werr)) {
5693                 return werr;
5694         }
5695
5696         Printer->document_started = true;
5697         *r->out.job_id = Printer->jobid;
5698
5699         return WERR_OK;
5700 }
5701
5702 /****************************************************************
5703  _spoolss_EndDocPrinter
5704 ****************************************************************/
5705
5706 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5707                               struct spoolss_EndDocPrinter *r)
5708 {
5709         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5710         NTSTATUS status;
5711         int snum;
5712
5713         if (!Printer) {
5714                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5715                         OUR_HANDLE(r->in.handle)));
5716                 return WERR_BADFID;
5717         }
5718
5719         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5720                 return WERR_BADFID;
5721         }
5722
5723         Printer->document_started = false;
5724         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5725         if (!NT_STATUS_IS_OK(status)) {
5726                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5727                           "print_job_end failed [%s]\n",
5728                           nt_errstr(status)));
5729         }
5730
5731         Printer->jobid = 0;
5732         return ntstatus_to_werror(status);
5733 }
5734
5735 /****************************************************************
5736  _spoolss_WritePrinter
5737 ****************************************************************/
5738
5739 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5740                              struct spoolss_WritePrinter *r)
5741 {
5742         ssize_t buffer_written;
5743         int snum;
5744         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5745
5746         if (!Printer) {
5747                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5748                         OUR_HANDLE(r->in.handle)));
5749                 *r->out.num_written = r->in._data_size;
5750                 return WERR_BADFID;
5751         }
5752
5753         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5754                 return WERR_BADFID;
5755
5756         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5757         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5758                                                    snum, Printer->jobid,
5759                                                    (const char *)r->in.data.data,
5760                                                    (size_t)r->in._data_size);
5761         if (buffer_written == (ssize_t)-1) {
5762                 *r->out.num_written = 0;
5763                 if (errno == ENOSPC)
5764                         return WERR_NO_SPOOL_SPACE;
5765                 else
5766                         return WERR_ACCESS_DENIED;
5767         }
5768
5769         *r->out.num_written = r->in._data_size;
5770
5771         return WERR_OK;
5772 }
5773
5774 /********************************************************************
5775  * api_spoolss_getprinter
5776  * called from the spoolss dispatcher
5777  *
5778  ********************************************************************/
5779
5780 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5781                               struct pipes_struct *p)
5782 {
5783         const struct auth_serversupplied_info *server_info = p->server_info;
5784         int snum;
5785         WERROR errcode = WERR_BADFUNC;
5786         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5787
5788         if (!Printer) {
5789                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5790                         OUR_HANDLE(handle)));
5791                 return WERR_BADFID;
5792         }
5793
5794         if (!get_printer_snum(p, handle, &snum, NULL))
5795                 return WERR_BADFID;
5796
5797         switch (command) {
5798         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5799                 errcode = print_queue_pause(server_info, p->msg_ctx, snum);
5800                 break;
5801         case SPOOLSS_PRINTER_CONTROL_RESUME:
5802         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5803                 errcode = print_queue_resume(server_info, p->msg_ctx, snum);
5804                 break;
5805         case SPOOLSS_PRINTER_CONTROL_PURGE:
5806                 errcode = print_queue_purge(server_info, p->msg_ctx, snum);
5807                 break;
5808         default:
5809                 return WERR_UNKNOWN_LEVEL;
5810         }
5811
5812         return errcode;
5813 }
5814
5815
5816 /****************************************************************
5817  _spoolss_AbortPrinter
5818  * From MSDN: "Deletes printer's spool file if printer is configured
5819  * for spooling"
5820 ****************************************************************/
5821
5822 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5823                              struct spoolss_AbortPrinter *r)
5824 {
5825         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5826         int             snum;
5827         WERROR          errcode = WERR_OK;
5828
5829         if (!Printer) {
5830                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5831                         OUR_HANDLE(r->in.handle)));
5832                 return WERR_BADFID;
5833         }
5834
5835         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5836                 return WERR_BADFID;
5837
5838         if (!Printer->document_started) {
5839                 return WERR_SPL_NO_STARTDOC;
5840         }
5841
5842         errcode = print_job_delete(p->server_info,
5843                                    p->msg_ctx,
5844                                    snum,
5845                                    Printer->jobid);
5846
5847         return errcode;
5848 }
5849
5850 /********************************************************************
5851  * called by spoolss_api_setprinter
5852  * when updating a printer description
5853  ********************************************************************/
5854
5855 static WERROR update_printer_sec(struct policy_handle *handle,
5856                                  struct pipes_struct *p,
5857                                  struct sec_desc_buf *secdesc_ctr)
5858 {
5859         struct spoolss_security_descriptor *new_secdesc = NULL;
5860         struct spoolss_security_descriptor *old_secdesc = NULL;
5861         const char *printer;
5862         WERROR result;
5863         int snum;
5864
5865         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5866
5867         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5868                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5869                          OUR_HANDLE(handle)));
5870
5871                 result = WERR_BADFID;
5872                 goto done;
5873         }
5874
5875         if (secdesc_ctr == NULL) {
5876                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5877                 result = WERR_INVALID_PARAM;
5878                 goto done;
5879         }
5880         printer = lp_const_servicename(snum);
5881
5882         /* Check the user has permissions to change the security
5883            descriptor.  By experimentation with two NT machines, the user
5884            requires Full Access to the printer to change security
5885            information. */
5886
5887         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5888                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5889                 result = WERR_ACCESS_DENIED;
5890                 goto done;
5891         }
5892
5893         /* NT seems to like setting the security descriptor even though
5894            nothing may have actually changed. */
5895         result = winreg_get_printer_secdesc(p->mem_ctx,
5896                                             get_server_info_system(),
5897                                             p->msg_ctx,
5898                                             printer,
5899                                             &old_secdesc);
5900         if (!W_ERROR_IS_OK(result)) {
5901                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5902                 result = WERR_BADFID;
5903                 goto done;
5904         }
5905
5906         if (DEBUGLEVEL >= 10) {
5907                 struct security_acl *the_acl;
5908                 int i;
5909
5910                 the_acl = old_secdesc->dacl;
5911                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5912                            printer, the_acl->num_aces));
5913
5914                 for (i = 0; i < the_acl->num_aces; i++) {
5915                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5916                                            &the_acl->aces[i].trustee),
5917                                   the_acl->aces[i].access_mask));
5918                 }
5919
5920                 the_acl = secdesc_ctr->sd->dacl;
5921
5922                 if (the_acl) {
5923                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5924                                    printer, the_acl->num_aces));
5925
5926                         for (i = 0; i < the_acl->num_aces; i++) {
5927                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5928                                                    &the_acl->aces[i].trustee),
5929                                            the_acl->aces[i].access_mask));
5930                         }
5931                 } else {
5932                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5933                 }
5934         }
5935
5936         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5937         if (new_secdesc == NULL) {
5938                 result = WERR_NOMEM;
5939                 goto done;
5940         }
5941
5942         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5943                 result = WERR_OK;
5944                 goto done;
5945         }
5946
5947         result = winreg_set_printer_secdesc(p->mem_ctx,
5948                                             get_server_info_system(),
5949                                             p->msg_ctx,
5950                                             printer,
5951                                             new_secdesc);
5952
5953  done:
5954         return result;
5955 }
5956
5957 /********************************************************************
5958  Canonicalize printer info from a client
5959  ********************************************************************/
5960
5961 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5962                              struct spoolss_SetPrinterInfo2 *info2,
5963                              int snum)
5964 {
5965         fstring printername;
5966         const char *p;
5967
5968         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5969                 "portname=%s drivername=%s comment=%s location=%s\n",
5970                 info2->servername, info2->printername, info2->sharename,
5971                 info2->portname, info2->drivername, info2->comment,
5972                 info2->location));
5973
5974         /* we force some elements to "correct" values */
5975         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5976         if (info2->servername == NULL) {
5977                 return false;
5978         }
5979         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5980         if (info2->sharename == NULL) {
5981                 return false;
5982         }
5983
5984         /* check to see if we allow printername != sharename */
5985         if (lp_force_printername(snum)) {
5986                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5987                                         global_myname(), info2->sharename);
5988         } else {
5989                 /* make sure printername is in \\server\printername format */
5990                 fstrcpy(printername, info2->printername);
5991                 p = printername;
5992                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5993                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5994                                 p++;
5995                 }
5996
5997                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5998                                         global_myname(), p);
5999         }
6000         if (info2->printername == NULL) {
6001                 return false;
6002         }
6003
6004         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6005         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6006
6007         return true;
6008 }
6009
6010 /****************************************************************************
6011 ****************************************************************************/
6012
6013 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6014 {
6015         char *cmd = lp_addport_cmd();
6016         char *command = NULL;
6017         int ret;
6018         bool is_print_op = false;
6019
6020         if ( !*cmd ) {
6021                 return WERR_ACCESS_DENIED;
6022         }
6023
6024         command = talloc_asprintf(ctx,
6025                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6026         if (!command) {
6027                 return WERR_NOMEM;
6028         }
6029
6030         if ( token )
6031                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6032
6033         DEBUG(10,("Running [%s]\n", command));
6034
6035         /********* BEGIN SePrintOperatorPrivilege **********/
6036
6037         if ( is_print_op )
6038                 become_root();
6039
6040         ret = smbrun(command, NULL);
6041
6042         if ( is_print_op )
6043                 unbecome_root();
6044
6045         /********* END SePrintOperatorPrivilege **********/
6046
6047         DEBUGADD(10,("returned [%d]\n", ret));
6048
6049         TALLOC_FREE(command);
6050
6051         if ( ret != 0 ) {
6052                 return WERR_ACCESS_DENIED;
6053         }
6054
6055         return WERR_OK;
6056 }
6057
6058 /****************************************************************************
6059 ****************************************************************************/
6060
6061 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6062                              struct spoolss_SetPrinterInfo2 *info2,
6063                              const char *remote_machine,
6064                              struct messaging_context *msg_ctx)
6065 {
6066         char *cmd = lp_addprinter_cmd();
6067         char **qlines;
6068         char *command = NULL;
6069         int numlines;
6070         int ret;
6071         int fd;
6072         bool is_print_op = false;
6073
6074         if (!remote_machine) {
6075                 return false;
6076         }
6077
6078         command = talloc_asprintf(ctx,
6079                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6080                         cmd, info2->printername, info2->sharename,
6081                         info2->portname, info2->drivername,
6082                         info2->location, info2->comment, remote_machine);
6083         if (!command) {
6084                 return false;
6085         }
6086
6087         if ( token )
6088                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6089
6090         DEBUG(10,("Running [%s]\n", command));
6091
6092         /********* BEGIN SePrintOperatorPrivilege **********/
6093
6094         if ( is_print_op )
6095                 become_root();
6096
6097         if ( (ret = smbrun(command, &fd)) == 0 ) {
6098                 /* Tell everyone we updated smb.conf. */
6099                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6100         }
6101
6102         if ( is_print_op )
6103                 unbecome_root();
6104
6105         /********* END SePrintOperatorPrivilege **********/
6106
6107         DEBUGADD(10,("returned [%d]\n", ret));
6108
6109         TALLOC_FREE(command);
6110
6111         if ( ret != 0 ) {
6112                 if (fd != -1)
6113                         close(fd);
6114                 return false;
6115         }
6116
6117         /* reload our services immediately */
6118         become_root();
6119         reload_services(msg_ctx, -1, false);
6120         unbecome_root();
6121
6122         numlines = 0;
6123         /* Get lines and convert them back to dos-codepage */
6124         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6125         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6126         close(fd);
6127
6128         /* Set the portname to what the script says the portname should be. */
6129         /* but don't require anything to be return from the script exit a good error code */
6130
6131         if (numlines) {
6132                 /* Set the portname to what the script says the portname should be. */
6133                 info2->portname = talloc_strdup(ctx, qlines[0]);
6134                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6135         }
6136
6137         TALLOC_FREE(qlines);
6138         return true;
6139 }
6140
6141 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6142                                const struct auth_serversupplied_info *server_info,
6143                                struct messaging_context *msg_ctx,
6144                                int snum,
6145                                struct spoolss_SetPrinterInfo2 *printer,
6146                                struct spoolss_PrinterInfo2 *old_printer)
6147 {
6148         bool force_update = (old_printer == NULL);
6149         const char *dnsdomname;
6150         const char *longname;
6151         const char *uncname;
6152         const char *spooling;
6153         DATA_BLOB buffer;
6154         WERROR result = WERR_OK;
6155
6156         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6157                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6158                 winreg_set_printer_dataex(mem_ctx,
6159                                           server_info,
6160                                           msg_ctx,
6161                                           printer->sharename,
6162                                           SPOOL_DSSPOOLER_KEY,
6163                                           SPOOL_REG_DRIVERNAME,
6164                                           REG_SZ,
6165                                           buffer.data,
6166                                           buffer.length);
6167
6168                 if (!force_update) {
6169                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6170                                 printer->drivername));
6171
6172                         notify_printer_driver(server_event_context(), msg_ctx,
6173                                               snum, printer->drivername ?
6174                                               printer->drivername : "");
6175                 }
6176         }
6177
6178         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6179                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6180                 winreg_set_printer_dataex(mem_ctx,
6181                                           server_info,
6182                                           msg_ctx,
6183                                           printer->sharename,
6184                                           SPOOL_DSSPOOLER_KEY,
6185                                           SPOOL_REG_DESCRIPTION,
6186                                           REG_SZ,
6187                                           buffer.data,
6188                                           buffer.length);
6189
6190                 if (!force_update) {
6191                         notify_printer_comment(server_event_context(), msg_ctx,
6192                                                snum, printer->comment ?
6193                                                printer->comment : "");
6194                 }
6195         }
6196
6197         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6198                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6199                 winreg_set_printer_dataex(mem_ctx,
6200                                           server_info,
6201                                           msg_ctx,
6202                                           printer->sharename,
6203                                           SPOOL_DSSPOOLER_KEY,
6204                                           SPOOL_REG_PRINTSHARENAME,
6205                                           REG_SZ,
6206                                           buffer.data,
6207                                           buffer.length);
6208
6209                 if (!force_update) {
6210                         notify_printer_sharename(server_event_context(),
6211                                                  msg_ctx,
6212                                                  snum, printer->sharename ?
6213                                                  printer->sharename : "");
6214                 }
6215         }
6216
6217         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6218                 const char *p;
6219
6220                 p = strrchr(printer->printername, '\\' );
6221                 if (p != NULL) {
6222                         p++;
6223                 } else {
6224                         p = printer->printername;
6225                 }
6226
6227                 push_reg_sz(mem_ctx, &buffer, p);
6228                 winreg_set_printer_dataex(mem_ctx,
6229                                           server_info,
6230                                           msg_ctx,
6231                                           printer->sharename,
6232                                           SPOOL_DSSPOOLER_KEY,
6233                                           SPOOL_REG_PRINTERNAME,
6234                                           REG_SZ,
6235                                           buffer.data,
6236                                           buffer.length);
6237
6238                 if (!force_update) {
6239                         notify_printer_printername(server_event_context(),
6240                                                    msg_ctx, snum, p ? p : "");
6241                 }
6242         }
6243
6244         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6245                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6246                 winreg_set_printer_dataex(mem_ctx,
6247                                           server_info,
6248                                           msg_ctx,
6249                                           printer->sharename,
6250                                           SPOOL_DSSPOOLER_KEY,
6251                                           SPOOL_REG_PORTNAME,
6252                                           REG_SZ,
6253                                           buffer.data,
6254                                           buffer.length);
6255
6256                 if (!force_update) {
6257                         notify_printer_port(server_event_context(),
6258                                             msg_ctx, snum, printer->portname ?
6259                                             printer->portname : "");
6260                 }
6261         }
6262
6263         if (force_update || !strequal(printer->location, old_printer->location)) {
6264                 push_reg_sz(mem_ctx, &buffer, printer->location);
6265                 winreg_set_printer_dataex(mem_ctx,
6266                                           server_info,
6267                                           msg_ctx,
6268                                           printer->sharename,
6269                                           SPOOL_DSSPOOLER_KEY,
6270                                           SPOOL_REG_LOCATION,
6271                                           REG_SZ,
6272                                           buffer.data,
6273                                           buffer.length);
6274
6275                 if (!force_update) {
6276                         notify_printer_location(server_event_context(),
6277                                                 msg_ctx, snum,
6278                                                 printer->location ?
6279                                                 printer->location : "");
6280                 }
6281         }
6282
6283         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6284                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6285                 winreg_set_printer_dataex(mem_ctx,
6286                                           server_info,
6287                                           msg_ctx,
6288                                           printer->sharename,
6289                                           SPOOL_DSSPOOLER_KEY,
6290                                           SPOOL_REG_PRINTSEPARATORFILE,
6291                                           REG_SZ,
6292                                           buffer.data,
6293                                           buffer.length);
6294
6295                 if (!force_update) {
6296                         notify_printer_sepfile(server_event_context(),
6297                                                msg_ctx, snum,
6298                                                printer->sepfile ?
6299                                                printer->sepfile : "");
6300                 }
6301         }
6302
6303         if (force_update || printer->starttime != old_printer->starttime) {
6304                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6305                 SIVAL(buffer.data, 0, printer->starttime);
6306                 winreg_set_printer_dataex(mem_ctx,
6307                                           server_info,
6308                                           msg_ctx,
6309                                           printer->sharename,
6310                                           SPOOL_DSSPOOLER_KEY,
6311                                           SPOOL_REG_PRINTSTARTTIME,
6312                                           REG_DWORD,
6313                                           buffer.data,
6314                                           buffer.length);
6315         }
6316
6317         if (force_update || printer->untiltime != old_printer->untiltime) {
6318                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6319                 SIVAL(buffer.data, 0, printer->untiltime);
6320                 winreg_set_printer_dataex(mem_ctx,
6321                                           server_info,
6322                                           msg_ctx,
6323                                           printer->sharename,
6324                                           SPOOL_DSSPOOLER_KEY,
6325                                           SPOOL_REG_PRINTENDTIME,
6326                                           REG_DWORD,
6327                                           buffer.data,
6328                                           buffer.length);
6329         }
6330
6331         if (force_update || printer->priority != old_printer->priority) {
6332                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6333                 SIVAL(buffer.data, 0, printer->priority);
6334                 winreg_set_printer_dataex(mem_ctx,
6335                                           server_info,
6336                                           msg_ctx,
6337                                           printer->sharename,
6338                                           SPOOL_DSSPOOLER_KEY,
6339                                           SPOOL_REG_PRIORITY,
6340                                           REG_DWORD,
6341                                           buffer.data,
6342                                           buffer.length);
6343         }
6344
6345         if (force_update || printer->attributes != old_printer->attributes) {
6346                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6347                 SIVAL(buffer.data, 0, (printer->attributes &
6348                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6349                 winreg_set_printer_dataex(mem_ctx,
6350                                           server_info,
6351                                           msg_ctx,
6352                                           printer->sharename,
6353                                           SPOOL_DSSPOOLER_KEY,
6354                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6355                                           REG_DWORD,
6356                                           buffer.data,
6357                                           buffer.length);
6358
6359                 switch (printer->attributes & 0x3) {
6360                         case 0:
6361                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6362                                 break;
6363                         case 1:
6364                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6365                                 break;
6366                         case 2:
6367                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6368                                 break;
6369                         default:
6370                                 spooling = "unknown";
6371                 }
6372                 push_reg_sz(mem_ctx, &buffer, spooling);
6373                 winreg_set_printer_dataex(mem_ctx,
6374                                           server_info,
6375                                           msg_ctx,
6376                                           printer->sharename,
6377                                           SPOOL_DSSPOOLER_KEY,
6378                                           SPOOL_REG_PRINTSPOOLING,
6379                                           REG_SZ,
6380                                           buffer.data,
6381                                           buffer.length);
6382         }
6383
6384         push_reg_sz(mem_ctx, &buffer, global_myname());
6385         winreg_set_printer_dataex(mem_ctx,
6386                                   server_info,
6387                                   msg_ctx,
6388                                   printer->sharename,
6389                                   SPOOL_DSSPOOLER_KEY,
6390                                   SPOOL_REG_SHORTSERVERNAME,
6391                                   REG_SZ,
6392                                   buffer.data,
6393                                   buffer.length);
6394
6395         dnsdomname = get_mydnsfullname();
6396         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6397                 longname = talloc_strdup(mem_ctx, dnsdomname);
6398         } else {
6399                 longname = talloc_strdup(mem_ctx, global_myname());
6400         }
6401         if (longname == NULL) {
6402                 result = WERR_NOMEM;
6403                 goto done;
6404         }
6405
6406         push_reg_sz(mem_ctx, &buffer, longname);
6407         winreg_set_printer_dataex(mem_ctx,
6408                                   server_info,
6409                                   msg_ctx,
6410                                   printer->sharename,
6411                                   SPOOL_DSSPOOLER_KEY,
6412                                   SPOOL_REG_SERVERNAME,
6413                                   REG_SZ,
6414                                   buffer.data,
6415                                   buffer.length);
6416
6417         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6418                                   global_myname(), printer->sharename);
6419         push_reg_sz(mem_ctx, &buffer, uncname);
6420         winreg_set_printer_dataex(mem_ctx,
6421                                   server_info,
6422                                   msg_ctx,
6423                                   printer->sharename,
6424                                   SPOOL_DSSPOOLER_KEY,
6425                                   SPOOL_REG_UNCNAME,
6426                                   REG_SZ,
6427                                   buffer.data,
6428                                   buffer.length);
6429
6430 done:
6431         return result;
6432 }
6433
6434 /********************************************************************
6435  * Called by spoolss_api_setprinter
6436  * when updating a printer description.
6437  ********************************************************************/
6438
6439 static WERROR update_printer(struct pipes_struct *p,
6440                              struct policy_handle *handle,
6441                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6442                              struct spoolss_DeviceMode *devmode)
6443 {
6444         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6445         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6446         struct spoolss_PrinterInfo2 *old_printer;
6447         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6448         int snum;
6449         WERROR result = WERR_OK;
6450         TALLOC_CTX *tmp_ctx;
6451
6452         DEBUG(8,("update_printer\n"));
6453
6454         tmp_ctx = talloc_new(p->mem_ctx);
6455         if (tmp_ctx == NULL) {
6456                 return WERR_NOMEM;
6457         }
6458
6459         if (!Printer) {
6460                 result = WERR_BADFID;
6461                 goto done;
6462         }
6463
6464         if (!get_printer_snum(p, handle, &snum, NULL)) {
6465                 result = WERR_BADFID;
6466                 goto done;
6467         }
6468
6469         result = winreg_get_printer(tmp_ctx,
6470                                     get_server_info_system(),
6471                                     p->msg_ctx,
6472                                     lp_const_servicename(snum),
6473                                     &old_printer);
6474         if (!W_ERROR_IS_OK(result)) {
6475                 result = WERR_BADFID;
6476                 goto done;
6477         }
6478
6479         /* Do sanity check on the requested changes for Samba */
6480         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6481                 result = WERR_INVALID_PARAM;
6482                 goto done;
6483         }
6484
6485         /* FIXME!!! If the driver has changed we really should verify that
6486            it is installed before doing much else   --jerry */
6487
6488         /* Check calling user has permission to update printer description */
6489         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6490                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6491                 result = WERR_ACCESS_DENIED;
6492                 goto done;
6493         }
6494
6495         /* Call addprinter hook */
6496         /* Check changes to see if this is really needed */
6497
6498         if (*lp_addprinter_cmd() &&
6499                         (!strequal(printer->drivername, old_printer->drivername) ||
6500                          !strequal(printer->comment, old_printer->comment) ||
6501                          !strequal(printer->portname, old_printer->portname) ||
6502                          !strequal(printer->location, old_printer->location)) )
6503         {
6504                 /* add_printer_hook() will call reload_services() */
6505                 if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
6506                                       printer, p->client_id->addr,
6507                                       p->msg_ctx)) {
6508                         result = WERR_ACCESS_DENIED;
6509                         goto done;
6510                 }
6511         }
6512
6513         update_dsspooler(tmp_ctx,
6514                          get_server_info_system(),
6515                          p->msg_ctx,
6516                          snum,
6517                          printer,
6518                          old_printer);
6519
6520         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6521
6522         if (devmode == NULL) {
6523                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6524         }
6525         result = winreg_update_printer(tmp_ctx,
6526                                        get_server_info_system(),
6527                                        p->msg_ctx,
6528                                        printer->sharename,
6529                                        printer_mask,
6530                                        printer,
6531                                        devmode,
6532                                        NULL);
6533
6534 done:
6535         talloc_free(tmp_ctx);
6536
6537         return result;
6538 }
6539
6540 /****************************************************************************
6541 ****************************************************************************/
6542 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6543                                            struct policy_handle *handle,
6544                                            struct spoolss_SetPrinterInfo7 *info7)
6545 {
6546 #ifdef HAVE_ADS
6547         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6548         WERROR result;
6549         int snum;
6550         struct printer_handle *Printer;
6551
6552         if ( lp_security() != SEC_ADS ) {
6553                 return WERR_UNKNOWN_LEVEL;
6554         }
6555
6556         Printer = find_printer_index_by_hnd(p, handle);
6557
6558         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6559
6560         if (!Printer)
6561                 return WERR_BADFID;
6562
6563         if (!get_printer_snum(p, handle, &snum, NULL))
6564                 return WERR_BADFID;
6565
6566         result = winreg_get_printer(p->mem_ctx,
6567                                     get_server_info_system(),
6568                                     p->msg_ctx,
6569                                     lp_servicename(snum),
6570                                     &pinfo2);
6571         if (!W_ERROR_IS_OK(result)) {
6572                 return WERR_BADFID;
6573         }
6574
6575         nt_printer_publish(pinfo2,
6576                            get_server_info_system(),
6577                            p->msg_ctx,
6578                            pinfo2,
6579                            info7->action);
6580
6581         TALLOC_FREE(pinfo2);
6582         return WERR_OK;
6583 #else
6584         return WERR_UNKNOWN_LEVEL;
6585 #endif
6586 }
6587
6588 /********************************************************************
6589  ********************************************************************/
6590
6591 static WERROR update_printer_devmode(struct pipes_struct *p,
6592                                      struct policy_handle *handle,
6593                                      struct spoolss_DeviceMode *devmode)
6594 {
6595         int snum;
6596         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6597         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6598
6599         DEBUG(8,("update_printer_devmode\n"));
6600
6601         if (!Printer) {
6602                 return WERR_BADFID;
6603         }
6604
6605         if (!get_printer_snum(p, handle, &snum, NULL)) {
6606                 return WERR_BADFID;
6607         }
6608
6609         /* Check calling user has permission to update printer description */
6610         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6611                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6612                 return WERR_ACCESS_DENIED;
6613         }
6614
6615         return winreg_update_printer(p->mem_ctx,
6616                                      get_server_info_system(),
6617                                      p->msg_ctx,
6618                                      lp_const_servicename(snum),
6619                                      info2_mask,
6620                                      NULL,
6621                                      devmode,
6622                                      NULL);
6623 }
6624
6625
6626 /****************************************************************
6627  _spoolss_SetPrinter
6628 ****************************************************************/
6629
6630 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6631                            struct spoolss_SetPrinter *r)
6632 {
6633         WERROR result;
6634
6635         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6636
6637         if (!Printer) {
6638                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6639                         OUR_HANDLE(r->in.handle)));
6640                 return WERR_BADFID;
6641         }
6642
6643         /* check the level */
6644         switch (r->in.info_ctr->level) {
6645                 case 0:
6646                         return control_printer(r->in.handle, r->in.command, p);
6647                 case 2:
6648                         result = update_printer(p, r->in.handle,
6649                                                 r->in.info_ctr,
6650                                                 r->in.devmode_ctr->devmode);
6651                         if (!W_ERROR_IS_OK(result))
6652                                 return result;
6653                         if (r->in.secdesc_ctr->sd)
6654                                 result = update_printer_sec(r->in.handle, p,
6655                                                             r->in.secdesc_ctr);
6656                         return result;
6657                 case 3:
6658                         return update_printer_sec(r->in.handle, p,
6659                                                   r->in.secdesc_ctr);
6660                 case 7:
6661                         return publish_or_unpublish_printer(p, r->in.handle,
6662                                                             r->in.info_ctr->info.info7);
6663                 case 8:
6664                         return update_printer_devmode(p, r->in.handle,
6665                                                       r->in.devmode_ctr->devmode);
6666                 default:
6667                         return WERR_UNKNOWN_LEVEL;
6668         }
6669 }
6670
6671 /****************************************************************
6672  _spoolss_FindClosePrinterNotify
6673 ****************************************************************/
6674
6675 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6676                                        struct spoolss_FindClosePrinterNotify *r)
6677 {
6678         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6679
6680         if (!Printer) {
6681                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6682                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6683                 return WERR_BADFID;
6684         }
6685
6686         if (Printer->notify.cli_chan != NULL &&
6687             Printer->notify.cli_chan->active_connections > 0) {
6688                 int snum = -1;
6689
6690                 if (Printer->printer_type == SPLHND_PRINTER) {
6691                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6692                                 return WERR_BADFID;
6693                         }
6694                 }
6695
6696                 srv_spoolss_replycloseprinter(snum, Printer);
6697         }
6698
6699         Printer->notify.flags=0;
6700         Printer->notify.options=0;
6701         Printer->notify.localmachine[0]='\0';
6702         Printer->notify.printerlocal=0;
6703         TALLOC_FREE(Printer->notify.option);
6704
6705         return WERR_OK;
6706 }
6707
6708 /****************************************************************
6709  _spoolss_AddJob
6710 ****************************************************************/
6711
6712 WERROR _spoolss_AddJob(struct pipes_struct *p,
6713                        struct spoolss_AddJob *r)
6714 {
6715         if (!r->in.buffer && (r->in.offered != 0)) {
6716                 return WERR_INVALID_PARAM;
6717         }
6718
6719         /* this is what a NT server returns for AddJob. AddJob must fail on
6720          * non-local printers */
6721
6722         if (r->in.level != 1) {
6723                 return WERR_UNKNOWN_LEVEL;
6724         }
6725
6726         return WERR_INVALID_PARAM;
6727 }
6728
6729 /****************************************************************************
6730 fill_job_info1
6731 ****************************************************************************/
6732
6733 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6734                              struct spoolss_JobInfo1 *r,
6735                              const print_queue_struct *queue,
6736                              int position, int snum,
6737                              struct spoolss_PrinterInfo2 *pinfo2)
6738 {
6739         struct tm *t;
6740
6741         t = gmtime(&queue->time);
6742
6743         r->job_id               = queue->job;
6744
6745         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6746         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6747         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6748         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6749         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6750         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6751         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6752         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6753         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6754         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6755         r->text_status          = talloc_strdup(mem_ctx, "");
6756         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6757
6758         r->status               = nt_printj_status(queue->status);
6759         r->priority             = queue->priority;
6760         r->position             = position;
6761         r->total_pages          = queue->page_count;
6762         r->pages_printed        = 0; /* ??? */
6763
6764         init_systemtime(&r->submitted, t);
6765
6766         return WERR_OK;
6767 }
6768
6769 /****************************************************************************
6770 fill_job_info2
6771 ****************************************************************************/
6772
6773 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6774                              struct spoolss_JobInfo2 *r,
6775                              const print_queue_struct *queue,
6776                              int position, int snum,
6777                              struct spoolss_PrinterInfo2 *pinfo2,
6778                              struct spoolss_DeviceMode *devmode)
6779 {
6780         struct tm *t;
6781
6782         t = gmtime(&queue->time);
6783
6784         r->job_id               = queue->job;
6785
6786         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6787         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6788         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6789         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6790         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6791         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6792         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6793         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6794         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6795         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6796         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6797         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6798         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6799         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6800         r->parameters           = talloc_strdup(mem_ctx, "");
6801         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6802         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6803         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6804
6805         r->devmode              = devmode;
6806
6807         r->text_status          = talloc_strdup(mem_ctx, "");
6808         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6809
6810         r->secdesc              = NULL;
6811
6812         r->status               = nt_printj_status(queue->status);
6813         r->priority             = queue->priority;
6814         r->position             = position;
6815         r->start_time           = 0;
6816         r->until_time           = 0;
6817         r->total_pages          = queue->page_count;
6818         r->size                 = queue->size;
6819         init_systemtime(&r->submitted, t);
6820         r->time                 = 0;
6821         r->pages_printed        = 0; /* ??? */
6822
6823         return WERR_OK;
6824 }
6825
6826 /****************************************************************************
6827 fill_job_info3
6828 ****************************************************************************/
6829
6830 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6831                              struct spoolss_JobInfo3 *r,
6832                              const print_queue_struct *queue,
6833                              const print_queue_struct *next_queue,
6834                              int position, int snum,
6835                              struct spoolss_PrinterInfo2 *pinfo2)
6836 {
6837         r->job_id               = queue->job;
6838         r->next_job_id          = 0;
6839         if (next_queue) {
6840                 r->next_job_id  = next_queue->job;
6841         }
6842         r->reserved             = 0;
6843
6844         return WERR_OK;
6845 }
6846
6847 /****************************************************************************
6848  Enumjobs at level 1.
6849 ****************************************************************************/
6850
6851 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6852                               const print_queue_struct *queue,
6853                               uint32_t num_queues, int snum,
6854                               struct spoolss_PrinterInfo2 *pinfo2,
6855                               union spoolss_JobInfo **info_p,
6856                               uint32_t *count)
6857 {
6858         union spoolss_JobInfo *info;
6859         int i;
6860         WERROR result = WERR_OK;
6861
6862         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6863         W_ERROR_HAVE_NO_MEMORY(info);
6864
6865         *count = num_queues;
6866
6867         for (i=0; i<*count; i++) {
6868                 result = fill_job_info1(info,
6869                                         &info[i].info1,
6870                                         &queue[i],
6871                                         i,
6872                                         snum,
6873                                         pinfo2);
6874                 if (!W_ERROR_IS_OK(result)) {
6875                         goto out;
6876                 }
6877         }
6878
6879  out:
6880         if (!W_ERROR_IS_OK(result)) {
6881                 TALLOC_FREE(info);
6882                 *count = 0;
6883                 return result;
6884         }
6885
6886         *info_p = info;
6887
6888         return WERR_OK;
6889 }
6890
6891 /****************************************************************************
6892  Enumjobs at level 2.
6893 ****************************************************************************/
6894
6895 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6896                               const print_queue_struct *queue,
6897                               uint32_t num_queues, int snum,
6898                               struct spoolss_PrinterInfo2 *pinfo2,
6899                               union spoolss_JobInfo **info_p,
6900                               uint32_t *count)
6901 {
6902         union spoolss_JobInfo *info;
6903         int i;
6904         WERROR result = WERR_OK;
6905
6906         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6907         W_ERROR_HAVE_NO_MEMORY(info);
6908
6909         *count = num_queues;
6910
6911         for (i=0; i<*count; i++) {
6912                 struct spoolss_DeviceMode *devmode;
6913
6914                 result = spoolss_create_default_devmode(info,
6915                                                         pinfo2->printername,
6916                                                         &devmode);
6917                 if (!W_ERROR_IS_OK(result)) {
6918                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6919                         goto out;
6920                 }
6921
6922                 result = fill_job_info2(info,
6923                                         &info[i].info2,
6924                                         &queue[i],
6925                                         i,
6926                                         snum,
6927                                         pinfo2,
6928                                         devmode);
6929                 if (!W_ERROR_IS_OK(result)) {
6930                         goto out;
6931                 }
6932         }
6933
6934  out:
6935         if (!W_ERROR_IS_OK(result)) {
6936                 TALLOC_FREE(info);
6937                 *count = 0;
6938                 return result;
6939         }
6940
6941         *info_p = info;
6942
6943         return WERR_OK;
6944 }
6945
6946 /****************************************************************************
6947  Enumjobs at level 3.
6948 ****************************************************************************/
6949
6950 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6951                               const print_queue_struct *queue,
6952                               uint32_t num_queues, int snum,
6953                               struct spoolss_PrinterInfo2 *pinfo2,
6954                               union spoolss_JobInfo **info_p,
6955                               uint32_t *count)
6956 {
6957         union spoolss_JobInfo *info;
6958         int i;
6959         WERROR result = WERR_OK;
6960
6961         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6962         W_ERROR_HAVE_NO_MEMORY(info);
6963
6964         *count = num_queues;
6965
6966         for (i=0; i<*count; i++) {
6967                 const print_queue_struct *next_queue = NULL;
6968
6969                 if (i+1 < *count) {
6970                         next_queue = &queue[i+1];
6971                 }
6972
6973                 result = fill_job_info3(info,
6974                                         &info[i].info3,
6975                                         &queue[i],
6976                                         next_queue,
6977                                         i,
6978                                         snum,
6979                                         pinfo2);
6980                 if (!W_ERROR_IS_OK(result)) {
6981                         goto out;
6982                 }
6983         }
6984
6985  out:
6986         if (!W_ERROR_IS_OK(result)) {
6987                 TALLOC_FREE(info);
6988                 *count = 0;
6989                 return result;
6990         }
6991
6992         *info_p = info;
6993
6994         return WERR_OK;
6995 }
6996
6997 /****************************************************************
6998  _spoolss_EnumJobs
6999 ****************************************************************/
7000
7001 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7002                          struct spoolss_EnumJobs *r)
7003 {
7004         WERROR result;
7005         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7006         int snum;
7007         print_status_struct prt_status;
7008         print_queue_struct *queue = NULL;
7009         uint32_t count;
7010
7011         /* that's an [in out] buffer */
7012
7013         if (!r->in.buffer && (r->in.offered != 0)) {
7014                 return WERR_INVALID_PARAM;
7015         }
7016
7017         DEBUG(4,("_spoolss_EnumJobs\n"));
7018
7019         *r->out.needed = 0;
7020         *r->out.count = 0;
7021         *r->out.info = NULL;
7022
7023         /* lookup the printer snum and tdb entry */
7024
7025         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7026                 return WERR_BADFID;
7027         }
7028
7029         result = winreg_get_printer(p->mem_ctx,
7030                                     get_server_info_system(),
7031                                     p->msg_ctx,
7032                                     lp_const_servicename(snum),
7033                                     &pinfo2);
7034         if (!W_ERROR_IS_OK(result)) {
7035                 return result;
7036         }
7037
7038         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7039         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7040                 count, prt_status.status, prt_status.message));
7041
7042         if (count == 0) {
7043                 SAFE_FREE(queue);
7044                 TALLOC_FREE(pinfo2);
7045                 return WERR_OK;
7046         }
7047
7048         switch (r->in.level) {
7049         case 1:
7050                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7051                                          pinfo2, r->out.info, r->out.count);
7052                 break;
7053         case 2:
7054                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7055                                          pinfo2, r->out.info, r->out.count);
7056                 break;
7057         case 3:
7058                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7059                                          pinfo2, r->out.info, r->out.count);
7060                 break;
7061         default:
7062                 result = WERR_UNKNOWN_LEVEL;
7063                 break;
7064         }
7065
7066         SAFE_FREE(queue);
7067         TALLOC_FREE(pinfo2);
7068
7069         if (!W_ERROR_IS_OK(result)) {
7070                 return result;
7071         }
7072
7073         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7074                                                      spoolss_EnumJobs, 
7075                                                      *r->out.info, r->in.level,
7076                                                      *r->out.count);
7077         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7078         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7079
7080         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7081 }
7082
7083 /****************************************************************
7084  _spoolss_ScheduleJob
7085 ****************************************************************/
7086
7087 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7088                             struct spoolss_ScheduleJob *r)
7089 {
7090         return WERR_OK;
7091 }
7092
7093 /****************************************************************
7094 ****************************************************************/
7095
7096 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7097                                struct messaging_context *msg_ctx,
7098                                const char *printer_name,
7099                                uint32_t job_id,
7100                                struct spoolss_SetJobInfo1 *r)
7101 {
7102         char *old_doc_name;
7103
7104         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7105                 return WERR_BADFID;
7106         }
7107
7108         if (strequal(old_doc_name, r->document_name)) {
7109                 return WERR_OK;
7110         }
7111
7112         if (!print_job_set_name(server_event_context(), msg_ctx,
7113                                 printer_name, job_id, r->document_name)) {
7114                 return WERR_BADFID;
7115         }
7116
7117         return WERR_OK;
7118 }
7119
7120 /****************************************************************
7121  _spoolss_SetJob
7122 ****************************************************************/
7123
7124 WERROR _spoolss_SetJob(struct pipes_struct *p,
7125                        struct spoolss_SetJob *r)
7126 {
7127         const struct auth_serversupplied_info *server_info = p->server_info;
7128         int snum;
7129         WERROR errcode = WERR_BADFUNC;
7130
7131         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7132                 return WERR_BADFID;
7133         }
7134
7135         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7136                 return WERR_INVALID_PRINTER_NAME;
7137         }
7138
7139         switch (r->in.command) {
7140         case SPOOLSS_JOB_CONTROL_CANCEL:
7141         case SPOOLSS_JOB_CONTROL_DELETE:
7142                 errcode = print_job_delete(server_info, p->msg_ctx,
7143                                            snum, r->in.job_id);
7144                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7145                         errcode = WERR_OK;
7146                 }
7147                 break;
7148         case SPOOLSS_JOB_CONTROL_PAUSE:
7149                 if (print_job_pause(server_info, p->msg_ctx,
7150                                     snum, r->in.job_id, &errcode)) {
7151                         errcode = WERR_OK;
7152                 }
7153                 break;
7154         case SPOOLSS_JOB_CONTROL_RESTART:
7155         case SPOOLSS_JOB_CONTROL_RESUME:
7156                 if (print_job_resume(server_info, p->msg_ctx,
7157                                      snum, r->in.job_id, &errcode)) {
7158                         errcode = WERR_OK;
7159                 }
7160                 break;
7161         case 0:
7162                 errcode = WERR_OK;
7163                 break;
7164         default:
7165                 return WERR_UNKNOWN_LEVEL;
7166         }
7167
7168         if (!W_ERROR_IS_OK(errcode)) {
7169                 return errcode;
7170         }
7171
7172         if (r->in.ctr == NULL) {
7173                 return errcode;
7174         }
7175
7176         switch (r->in.ctr->level) {
7177         case 1:
7178                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7179                                            lp_const_servicename(snum),
7180                                            r->in.job_id,
7181                                            r->in.ctr->info.info1);
7182                 break;
7183         case 2:
7184         case 3:
7185         case 4:
7186         default:
7187                 return WERR_UNKNOWN_LEVEL;
7188         }
7189
7190         return errcode;
7191 }
7192
7193 /****************************************************************************
7194  Enumerates all printer drivers by level and architecture.
7195 ****************************************************************************/
7196
7197 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7198                                                        const struct auth_serversupplied_info *server_info,
7199                                                        struct messaging_context *msg_ctx,
7200                                                        const char *servername,
7201                                                        const char *architecture,
7202                                                        uint32_t level,
7203                                                        union spoolss_DriverInfo **info_p,
7204                                                        uint32_t *count_p)
7205 {
7206         int i;
7207         uint32_t version;
7208         struct spoolss_DriverInfo8 *driver;
7209         union spoolss_DriverInfo *info = NULL;
7210         uint32_t count = 0;
7211         WERROR result = WERR_OK;
7212         uint32_t num_drivers;
7213         const char **drivers;
7214
7215         *count_p = 0;
7216         *info_p = NULL;
7217
7218         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7219                 result = winreg_get_driver_list(mem_ctx, server_info, msg_ctx,
7220                                                 architecture, version,
7221                                                 &num_drivers, &drivers);
7222                 if (!W_ERROR_IS_OK(result)) {
7223                         goto out;
7224                 }
7225                 DEBUG(4, ("we have:[%d] drivers in environment"
7226                           " [%s] and version [%d]\n",
7227                           num_drivers, architecture, version));
7228
7229                 if (num_drivers != 0) {
7230                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7231                                                     union spoolss_DriverInfo,
7232                                                     count + num_drivers);
7233                         if (!info) {
7234                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7235                                         "failed to enlarge driver info buffer!\n"));
7236                                 result = WERR_NOMEM;
7237                                 goto out;
7238                         }
7239                 }
7240
7241                 for (i = 0; i < num_drivers; i++) {
7242                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7243
7244                         result = winreg_get_driver(mem_ctx, server_info,
7245                                                    msg_ctx,
7246                                                    architecture, drivers[i],
7247                                                    version, &driver);
7248                         if (!W_ERROR_IS_OK(result)) {
7249                                 goto out;
7250                         }
7251
7252                         switch (level) {
7253                         case 1:
7254                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7255                                                                    driver, servername);
7256                                 break;
7257                         case 2:
7258                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7259                                                                    driver, servername);
7260                                 break;
7261                         case 3:
7262                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7263                                                                    driver, servername);
7264                                 break;
7265                         case 4:
7266                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7267                                                                    driver, servername);
7268                                 break;
7269                         case 5:
7270                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7271                                                                    driver, servername);
7272                                 break;
7273                         case 6:
7274                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7275                                                                    driver, servername);
7276                                 break;
7277                         case 8:
7278                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7279                                                                    driver, servername);
7280                                 break;
7281                         default:
7282                                 result = WERR_UNKNOWN_LEVEL;
7283                                 break;
7284                         }
7285
7286                         TALLOC_FREE(driver);
7287
7288                         if (!W_ERROR_IS_OK(result)) {
7289                                 goto out;
7290                         }
7291                 }
7292
7293                 count += num_drivers;
7294                 TALLOC_FREE(drivers);
7295         }
7296
7297  out:
7298         TALLOC_FREE(drivers);
7299
7300         if (!W_ERROR_IS_OK(result)) {
7301                 TALLOC_FREE(info);
7302                 return result;
7303         }
7304
7305         *info_p = info;
7306         *count_p = count;
7307
7308         return WERR_OK;
7309 }
7310
7311 /****************************************************************************
7312  Enumerates all printer drivers by level.
7313 ****************************************************************************/
7314
7315 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7316                                        const struct auth_serversupplied_info *server_info,
7317                                        struct messaging_context *msg_ctx,
7318                                        const char *servername,
7319                                        const char *architecture,
7320                                        uint32_t level,
7321                                        union spoolss_DriverInfo **info_p,
7322                                        uint32_t *count_p)
7323 {
7324         uint32_t a,i;
7325         WERROR result = WERR_OK;
7326
7327         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7328
7329                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7330
7331                         union spoolss_DriverInfo *info = NULL;
7332                         uint32_t count = 0;
7333
7334                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7335                                                                           server_info,
7336                                                                           msg_ctx,
7337                                                                           servername,
7338                                                                           archi_table[a].long_archi,
7339                                                                           level,
7340                                                                           &info,
7341                                                                           &count);
7342                         if (!W_ERROR_IS_OK(result)) {
7343                                 continue;
7344                         }
7345
7346                         for (i=0; i < count; i++) {
7347                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7348                                              info[i], info_p, count_p);
7349                         }
7350                 }
7351
7352                 return result;
7353         }
7354
7355         return enumprinterdrivers_level_by_architecture(mem_ctx,
7356                                                         server_info,
7357                                                         msg_ctx,
7358                                                         servername,
7359                                                         architecture,
7360                                                         level,
7361                                                         info_p,
7362                                                         count_p);
7363 }
7364
7365 /****************************************************************
7366  _spoolss_EnumPrinterDrivers
7367 ****************************************************************/
7368
7369 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7370                                    struct spoolss_EnumPrinterDrivers *r)
7371 {
7372         const char *cservername;
7373         WERROR result;
7374
7375         /* that's an [in out] buffer */
7376
7377         if (!r->in.buffer && (r->in.offered != 0)) {
7378                 return WERR_INVALID_PARAM;
7379         }
7380
7381         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7382
7383         *r->out.needed = 0;
7384         *r->out.count = 0;
7385         *r->out.info = NULL;
7386
7387         cservername = canon_servername(r->in.server);
7388
7389         if (!is_myname_or_ipaddr(cservername)) {
7390                 return WERR_UNKNOWN_PRINTER_DRIVER;
7391         }
7392
7393         result = enumprinterdrivers_level(p->mem_ctx,
7394                                           get_server_info_system(),
7395                                           p->msg_ctx,
7396                                           cservername,
7397                                           r->in.environment,
7398                                           r->in.level,
7399                                           r->out.info,
7400                                           r->out.count);
7401         if (!W_ERROR_IS_OK(result)) {
7402                 return result;
7403         }
7404
7405         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7406                                                      spoolss_EnumPrinterDrivers, 
7407                                                      *r->out.info, r->in.level,
7408                                                      *r->out.count);
7409         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7410         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7411
7412         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7413 }
7414
7415 /****************************************************************
7416  _spoolss_EnumForms
7417 ****************************************************************/
7418
7419 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7420                           struct spoolss_EnumForms *r)
7421 {
7422         WERROR result;
7423
7424         *r->out.count = 0;
7425         *r->out.needed = 0;
7426         *r->out.info = NULL;
7427
7428         /* that's an [in out] buffer */
7429
7430         if (!r->in.buffer && (r->in.offered != 0) ) {
7431                 return WERR_INVALID_PARAM;
7432         }
7433
7434         DEBUG(4,("_spoolss_EnumForms\n"));
7435         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7436         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7437
7438         switch (r->in.level) {
7439         case 1:
7440                 result = winreg_printer_enumforms1(p->mem_ctx,
7441                                                    get_server_info_system(),
7442                                                    p->msg_ctx,
7443                                                    r->out.count,
7444                                                    r->out.info);
7445                 break;
7446         default:
7447                 result = WERR_UNKNOWN_LEVEL;
7448                 break;
7449         }
7450
7451         if (!W_ERROR_IS_OK(result)) {
7452                 return result;
7453         }
7454
7455         if (*r->out.count == 0) {
7456                 return WERR_NO_MORE_ITEMS;
7457         }
7458
7459         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7460                                                      spoolss_EnumForms, 
7461                                                      *r->out.info, r->in.level,
7462                                                      *r->out.count);
7463         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7464         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7465
7466         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7467 }
7468
7469 /****************************************************************
7470  _spoolss_GetForm
7471 ****************************************************************/
7472
7473 WERROR _spoolss_GetForm(struct pipes_struct *p,
7474                         struct spoolss_GetForm *r)
7475 {
7476         WERROR result;
7477
7478         /* that's an [in out] buffer */
7479
7480         if (!r->in.buffer && (r->in.offered != 0)) {
7481                 return WERR_INVALID_PARAM;
7482         }
7483
7484         DEBUG(4,("_spoolss_GetForm\n"));
7485         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7486         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7487
7488         switch (r->in.level) {
7489         case 1:
7490                 result = winreg_printer_getform1(p->mem_ctx,
7491                                                  get_server_info_system(),
7492                                                  p->msg_ctx,
7493                                                  r->in.form_name,
7494                                                  &r->out.info->info1);
7495                 break;
7496         default:
7497                 result = WERR_UNKNOWN_LEVEL;
7498                 break;
7499         }
7500
7501         if (!W_ERROR_IS_OK(result)) {
7502                 TALLOC_FREE(r->out.info);
7503                 return result;
7504         }
7505
7506         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, 
7507                                                r->out.info, r->in.level);
7508         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7509
7510         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7511 }
7512
7513 /****************************************************************************
7514 ****************************************************************************/
7515
7516 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7517                           struct spoolss_PortInfo1 *r,
7518                           const char *name)
7519 {
7520         r->port_name = talloc_strdup(mem_ctx, name);
7521         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7522
7523         return WERR_OK;
7524 }
7525
7526 /****************************************************************************
7527  TODO: This probably needs distinguish between TCP/IP and Local ports
7528  somehow.
7529 ****************************************************************************/
7530
7531 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7532                           struct spoolss_PortInfo2 *r,
7533                           const char *name)
7534 {
7535         r->port_name = talloc_strdup(mem_ctx, name);
7536         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7537
7538         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7539         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7540
7541         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7542         W_ERROR_HAVE_NO_MEMORY(r->description);
7543
7544         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7545         r->reserved = 0;
7546
7547         return WERR_OK;
7548 }
7549
7550
7551 /****************************************************************************
7552  wrapper around the enumer ports command
7553 ****************************************************************************/
7554
7555 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7556 {
7557         char *cmd = lp_enumports_cmd();
7558         char **qlines = NULL;
7559         char *command = NULL;
7560         int numlines;
7561         int ret;
7562         int fd;
7563
7564         *count = 0;
7565         *lines = NULL;
7566
7567         /* if no hook then just fill in the default port */
7568
7569         if ( !*cmd ) {
7570                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7571                         return WERR_NOMEM;
7572                 }
7573                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7574                         TALLOC_FREE(qlines);
7575                         return WERR_NOMEM;
7576                 }
7577                 qlines[1] = NULL;
7578                 numlines = 1;
7579         }
7580         else {
7581                 /* we have a valid enumport command */
7582
7583                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7584                 if (!command) {
7585                         return WERR_NOMEM;
7586                 }
7587
7588                 DEBUG(10,("Running [%s]\n", command));
7589                 ret = smbrun(command, &fd);
7590                 DEBUG(10,("Returned [%d]\n", ret));
7591                 TALLOC_FREE(command);
7592                 if (ret != 0) {
7593                         if (fd != -1) {
7594                                 close(fd);
7595                         }
7596                         return WERR_ACCESS_DENIED;
7597                 }
7598
7599                 numlines = 0;
7600                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7601                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7602                 close(fd);
7603         }
7604
7605         *count = numlines;
7606         *lines = qlines;
7607
7608         return WERR_OK;
7609 }
7610
7611 /****************************************************************************
7612  enumports level 1.
7613 ****************************************************************************/
7614
7615 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7616                                 union spoolss_PortInfo **info_p,
7617                                 uint32_t *count)
7618 {
7619         union spoolss_PortInfo *info = NULL;
7620         int i=0;
7621         WERROR result = WERR_OK;
7622         char **qlines = NULL;
7623         int numlines = 0;
7624
7625         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7626         if (!W_ERROR_IS_OK(result)) {
7627                 goto out;
7628         }
7629
7630         if (numlines) {
7631                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7632                 if (!info) {
7633                         DEBUG(10,("Returning WERR_NOMEM\n"));
7634                         result = WERR_NOMEM;
7635                         goto out;
7636                 }
7637
7638                 for (i=0; i<numlines; i++) {
7639                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7640                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7641                         if (!W_ERROR_IS_OK(result)) {
7642                                 goto out;
7643                         }
7644                 }
7645         }
7646         TALLOC_FREE(qlines);
7647
7648 out:
7649         if (!W_ERROR_IS_OK(result)) {
7650                 TALLOC_FREE(info);
7651                 TALLOC_FREE(qlines);
7652                 *count = 0;
7653                 *info_p = NULL;
7654                 return result;
7655         }
7656
7657         *info_p = info;
7658         *count = numlines;
7659
7660         return WERR_OK;
7661 }
7662
7663 /****************************************************************************
7664  enumports level 2.
7665 ****************************************************************************/
7666
7667 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7668                                 union spoolss_PortInfo **info_p,
7669                                 uint32_t *count)
7670 {
7671         union spoolss_PortInfo *info = NULL;
7672         int i=0;
7673         WERROR result = WERR_OK;
7674         char **qlines = NULL;
7675         int numlines = 0;
7676
7677         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7678         if (!W_ERROR_IS_OK(result)) {
7679                 goto out;
7680         }
7681
7682         if (numlines) {
7683                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7684                 if (!info) {
7685                         DEBUG(10,("Returning WERR_NOMEM\n"));
7686                         result = WERR_NOMEM;
7687                         goto out;
7688                 }
7689
7690                 for (i=0; i<numlines; i++) {
7691                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7692                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7693                         if (!W_ERROR_IS_OK(result)) {
7694                                 goto out;
7695                         }
7696                 }
7697         }
7698         TALLOC_FREE(qlines);
7699
7700 out:
7701         if (!W_ERROR_IS_OK(result)) {
7702                 TALLOC_FREE(info);
7703                 TALLOC_FREE(qlines);
7704                 *count = 0;
7705                 *info_p = NULL;
7706                 return result;
7707         }
7708
7709         *info_p = info;
7710         *count = numlines;
7711
7712         return WERR_OK;
7713 }
7714
7715 /****************************************************************
7716  _spoolss_EnumPorts
7717 ****************************************************************/
7718
7719 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7720                           struct spoolss_EnumPorts *r)
7721 {
7722         WERROR result;
7723
7724         /* that's an [in out] buffer */
7725
7726         if (!r->in.buffer && (r->in.offered != 0)) {
7727                 return WERR_INVALID_PARAM;
7728         }
7729
7730         DEBUG(4,("_spoolss_EnumPorts\n"));
7731
7732         *r->out.count = 0;
7733         *r->out.needed = 0;
7734         *r->out.info = NULL;
7735
7736         switch (r->in.level) {
7737         case 1:
7738                 result = enumports_level_1(p->mem_ctx, r->out.info,
7739                                            r->out.count);
7740                 break;
7741         case 2:
7742                 result = enumports_level_2(p->mem_ctx, r->out.info,
7743                                            r->out.count);
7744                 break;
7745         default:
7746                 return WERR_UNKNOWN_LEVEL;
7747         }
7748
7749         if (!W_ERROR_IS_OK(result)) {
7750                 return result;
7751         }
7752
7753         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7754                                                      spoolss_EnumPorts, 
7755                                                      *r->out.info, r->in.level,
7756                                                      *r->out.count);
7757         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7758         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7759
7760         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7761 }
7762
7763 /****************************************************************************
7764 ****************************************************************************/
7765
7766 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7767                                            const char *server,
7768                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7769                                            struct spoolss_DeviceMode *devmode,
7770                                            struct security_descriptor *secdesc,
7771                                            struct spoolss_UserLevelCtr *user_ctr,
7772                                            struct policy_handle *handle)
7773 {
7774         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7775         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7776         int     snum;
7777         WERROR err = WERR_OK;
7778
7779         /* samba does not have a concept of local, non-shared printers yet, so
7780          * make sure we always setup sharename - gd */
7781         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7782             (info2->printername != NULL && info2->printername[0] != '\0')) {
7783                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7784                         "no sharename has been set, setting printername %s as sharename\n",
7785                         info2->printername));
7786                 info2->sharename = info2->printername;
7787         }
7788
7789         /* check to see if the printer already exists */
7790         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7791                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7792                         info2->sharename));
7793                 return WERR_PRINTER_ALREADY_EXISTS;
7794         }
7795
7796         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7797                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7798                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7799                                 info2->printername));
7800                         return WERR_PRINTER_ALREADY_EXISTS;
7801                 }
7802         }
7803
7804         /* validate printer info struct */
7805         if (!info2->printername || strlen(info2->printername) == 0) {
7806                 return WERR_INVALID_PRINTER_NAME;
7807         }
7808         if (!info2->portname || strlen(info2->portname) == 0) {
7809                 return WERR_UNKNOWN_PORT;
7810         }
7811         if (!info2->drivername || strlen(info2->drivername) == 0) {
7812                 return WERR_UNKNOWN_PRINTER_DRIVER;
7813         }
7814         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7815                 return WERR_UNKNOWN_PRINTPROCESSOR;
7816         }
7817
7818         /* FIXME!!!  smbd should check to see if the driver is installed before
7819            trying to add a printer like this  --jerry */
7820
7821         if (*lp_addprinter_cmd() ) {
7822                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7823                                        info2, p->client_id->addr,
7824                                        p->msg_ctx) ) {
7825                         return WERR_ACCESS_DENIED;
7826                 }
7827         } else {
7828                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7829                         "smb.conf parameter \"addprinter command\" is defined. This"
7830                         "parameter must exist for this call to succeed\n",
7831                         info2->sharename ));
7832         }
7833
7834         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7835                 return WERR_ACCESS_DENIED;
7836         }
7837
7838         /* you must be a printer admin to add a new printer */
7839         if (!print_access_check(p->server_info,
7840                                 p->msg_ctx,
7841                                 snum,
7842                                 PRINTER_ACCESS_ADMINISTER)) {
7843                 return WERR_ACCESS_DENIED;
7844         }
7845
7846         /*
7847          * Do sanity check on the requested changes for Samba.
7848          */
7849
7850         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7851                 return WERR_INVALID_PARAM;
7852         }
7853
7854         if (devmode == NULL) {
7855                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7856         }
7857
7858         update_dsspooler(p->mem_ctx,
7859                          get_server_info_system(),
7860                          p->msg_ctx,
7861                          0,
7862                          info2,
7863                          NULL);
7864
7865         err = winreg_update_printer(p->mem_ctx,
7866                                     get_server_info_system(),
7867                                     p->msg_ctx,
7868                                     info2->sharename,
7869                                     info2_mask,
7870                                     info2,
7871                                     devmode,
7872                                     secdesc);
7873         if (!W_ERROR_IS_OK(err)) {
7874                 return err;
7875         }
7876
7877         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7878         if (!W_ERROR_IS_OK(err)) {
7879                 /* Handle open failed - remove addition. */
7880                 ZERO_STRUCTP(handle);
7881                 return err;
7882         }
7883
7884         return WERR_OK;
7885 }
7886
7887 /****************************************************************
7888  _spoolss_AddPrinterEx
7889 ****************************************************************/
7890
7891 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7892                              struct spoolss_AddPrinterEx *r)
7893 {
7894         switch (r->in.info_ctr->level) {
7895         case 1:
7896                 /* we don't handle yet */
7897                 /* but I know what to do ... */
7898                 return WERR_UNKNOWN_LEVEL;
7899         case 2:
7900                 return spoolss_addprinterex_level_2(p, r->in.server,
7901                                                     r->in.info_ctr,
7902                                                     r->in.devmode_ctr->devmode,
7903                                                     r->in.secdesc_ctr->sd,
7904                                                     r->in.userlevel_ctr,
7905                                                     r->out.handle);
7906         default:
7907                 return WERR_UNKNOWN_LEVEL;
7908         }
7909 }
7910
7911 /****************************************************************
7912  _spoolss_AddPrinter
7913 ****************************************************************/
7914
7915 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7916                            struct spoolss_AddPrinter *r)
7917 {
7918         struct spoolss_AddPrinterEx a;
7919         struct spoolss_UserLevelCtr userlevel_ctr;
7920
7921         ZERO_STRUCT(userlevel_ctr);
7922
7923         userlevel_ctr.level = 1;
7924
7925         a.in.server             = r->in.server;
7926         a.in.info_ctr           = r->in.info_ctr;
7927         a.in.devmode_ctr        = r->in.devmode_ctr;
7928         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7929         a.in.userlevel_ctr      = &userlevel_ctr;
7930         a.out.handle            = r->out.handle;
7931
7932         return _spoolss_AddPrinterEx(p, &a);
7933 }
7934
7935 /****************************************************************
7936  _spoolss_AddPrinterDriverEx
7937 ****************************************************************/
7938
7939 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7940                                    struct spoolss_AddPrinterDriverEx *r)
7941 {
7942         WERROR err = WERR_OK;
7943         const char *driver_name = NULL;
7944         uint32_t version;
7945         const char *fn;
7946
7947         switch (p->opnum) {
7948                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7949                         fn = "_spoolss_AddPrinterDriver";
7950                         break;
7951                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7952                         fn = "_spoolss_AddPrinterDriverEx";
7953                         break;
7954                 default:
7955                         return WERR_INVALID_PARAM;
7956         }
7957
7958         /*
7959          * we only support the semantics of AddPrinterDriver()
7960          * i.e. only copy files that are newer than existing ones
7961          */
7962
7963         if (r->in.flags == 0) {
7964                 return WERR_INVALID_PARAM;
7965         }
7966
7967         if (r->in.flags != APD_COPY_NEW_FILES) {
7968                 return WERR_ACCESS_DENIED;
7969         }
7970
7971         /* FIXME */
7972         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7973                 /* Clever hack from Martin Zielinski <mz@seh.de>
7974                  * to allow downgrade from level 8 (Vista).
7975                  */
7976                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7977                         r->in.info_ctr->level));
7978                 return WERR_UNKNOWN_LEVEL;
7979         }
7980
7981         DEBUG(5,("Cleaning driver's information\n"));
7982         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7983         if (!W_ERROR_IS_OK(err))
7984                 goto done;
7985
7986         DEBUG(5,("Moving driver to final destination\n"));
7987         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7988                                                               &err)) ) {
7989                 goto done;
7990         }
7991
7992         err = winreg_add_driver(p->mem_ctx,
7993                                 get_server_info_system(),
7994                                 p->msg_ctx,
7995                                 r->in.info_ctr,
7996                                 &driver_name,
7997                                 &version);
7998         if (!W_ERROR_IS_OK(err)) {
7999                 goto done;
8000         }
8001
8002         /*
8003          * I think this is where he DrvUpgradePrinter() hook would be
8004          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8005          * server.  Right now, we just need to send ourselves a message
8006          * to update each printer bound to this driver.   --jerry
8007          */
8008
8009         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8010                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8011                         fn, driver_name));
8012         }
8013
8014 done:
8015         return err;
8016 }
8017
8018 /****************************************************************
8019  _spoolss_AddPrinterDriver
8020 ****************************************************************/
8021
8022 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8023                                  struct spoolss_AddPrinterDriver *r)
8024 {
8025         struct spoolss_AddPrinterDriverEx a;
8026
8027         switch (r->in.info_ctr->level) {
8028         case 2:
8029         case 3:
8030         case 4:
8031         case 5:
8032                 break;
8033         default:
8034                 return WERR_UNKNOWN_LEVEL;
8035         }
8036
8037         a.in.servername         = r->in.servername;
8038         a.in.info_ctr           = r->in.info_ctr;
8039         a.in.flags              = APD_COPY_NEW_FILES;
8040
8041         return _spoolss_AddPrinterDriverEx(p, &a);
8042 }
8043
8044 /****************************************************************************
8045 ****************************************************************************/
8046
8047 struct _spoolss_paths {
8048         int type;
8049         const char *share;
8050         const char *dir;
8051 };
8052
8053 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8054
8055 static const struct _spoolss_paths spoolss_paths[]= {
8056         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8057         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8058 };
8059
8060 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8061                                           const char *servername,
8062                                           const char *environment,
8063                                           int component,
8064                                           char **path)
8065 {
8066         const char *pservername = NULL;
8067         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8068         const char *short_archi;
8069
8070         *path = NULL;
8071
8072         /* environment may be empty */
8073         if (environment && strlen(environment)) {
8074                 long_archi = environment;
8075         }
8076
8077         /* servername may be empty */
8078         if (servername && strlen(servername)) {
8079                 pservername = canon_servername(servername);
8080
8081                 if (!is_myname_or_ipaddr(pservername)) {
8082                         return WERR_INVALID_PARAM;
8083                 }
8084         }
8085
8086         if (!(short_archi = get_short_archi(long_archi))) {
8087                 return WERR_INVALID_ENVIRONMENT;
8088         }
8089
8090         switch (component) {
8091         case SPOOLSS_PRTPROCS_PATH:
8092         case SPOOLSS_DRIVER_PATH:
8093                 if (pservername) {
8094                         *path = talloc_asprintf(mem_ctx,
8095                                         "\\\\%s\\%s\\%s",
8096                                         pservername,
8097                                         spoolss_paths[component].share,
8098                                         short_archi);
8099                 } else {
8100                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8101                                         SPOOLSS_DEFAULT_SERVER_PATH,
8102                                         spoolss_paths[component].dir,
8103                                         short_archi);
8104                 }
8105                 break;
8106         default:
8107                 return WERR_INVALID_PARAM;
8108         }
8109
8110         if (!*path) {
8111                 return WERR_NOMEM;
8112         }
8113
8114         return WERR_OK;
8115 }
8116
8117 /****************************************************************************
8118 ****************************************************************************/
8119
8120 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8121                                           const char *servername,
8122                                           const char *environment,
8123                                           struct spoolss_DriverDirectoryInfo1 *r)
8124 {
8125         WERROR werr;
8126         char *path = NULL;
8127
8128         werr = compose_spoolss_server_path(mem_ctx,
8129                                            servername,
8130                                            environment,
8131                                            SPOOLSS_DRIVER_PATH,
8132                                            &path);
8133         if (!W_ERROR_IS_OK(werr)) {
8134                 return werr;
8135         }
8136
8137         DEBUG(4,("printer driver directory: [%s]\n", path));
8138
8139         r->directory_name = path;
8140
8141         return WERR_OK;
8142 }
8143
8144 /****************************************************************
8145  _spoolss_GetPrinterDriverDirectory
8146 ****************************************************************/
8147
8148 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8149                                           struct spoolss_GetPrinterDriverDirectory *r)
8150 {
8151         WERROR werror;
8152
8153         /* that's an [in out] buffer */
8154
8155         if (!r->in.buffer && (r->in.offered != 0)) {
8156                 return WERR_INVALID_PARAM;
8157         }
8158
8159         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8160                 r->in.level));
8161
8162         *r->out.needed = 0;
8163
8164         /* r->in.level is ignored */
8165
8166         werror = getprinterdriverdir_level_1(p->mem_ctx,
8167                                              r->in.server,
8168                                              r->in.environment,
8169                                              &r->out.info->info1);
8170         if (!W_ERROR_IS_OK(werror)) {
8171                 TALLOC_FREE(r->out.info);
8172                 return werror;
8173         }
8174
8175         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, 
8176                                                r->out.info, r->in.level);
8177         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8178
8179         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8180 }
8181
8182 /****************************************************************
8183  _spoolss_EnumPrinterData
8184 ****************************************************************/
8185
8186 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8187                                 struct spoolss_EnumPrinterData *r)
8188 {
8189         WERROR result;
8190         struct spoolss_EnumPrinterDataEx r2;
8191         uint32_t count;
8192         struct spoolss_PrinterEnumValues *info, *val = NULL;
8193         uint32_t needed;
8194
8195         r2.in.handle    = r->in.handle;
8196         r2.in.key_name  = "PrinterDriverData";
8197         r2.in.offered   = 0;
8198         r2.out.count    = &count;
8199         r2.out.info     = &info;
8200         r2.out.needed   = &needed;
8201
8202         result = _spoolss_EnumPrinterDataEx(p, &r2);
8203         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8204                 r2.in.offered = needed;
8205                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8206         }
8207         if (!W_ERROR_IS_OK(result)) {
8208                 return result;
8209         }
8210
8211         /*
8212          * The NT machine wants to know the biggest size of value and data
8213          *
8214          * cf: MSDN EnumPrinterData remark section
8215          */
8216
8217         if (!r->in.value_offered && !r->in.data_offered) {
8218                 uint32_t biggest_valuesize = 0;
8219                 uint32_t biggest_datasize = 0;
8220                 int i, name_length;
8221
8222                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8223
8224                 for (i=0; i<count; i++) {
8225
8226                         name_length = strlen(info[i].value_name);
8227                         if (strlen(info[i].value_name) > biggest_valuesize) {
8228                                 biggest_valuesize = name_length;
8229                         }
8230
8231                         if (info[i].data_length > biggest_datasize) {
8232                                 biggest_datasize = info[i].data_length;
8233                         }
8234
8235                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8236                                 biggest_datasize));
8237                 }
8238
8239                 /* the value is an UNICODE string but real_value_size is the length
8240                    in bytes including the trailing 0 */
8241
8242                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8243                 *r->out.data_needed  = biggest_datasize;
8244
8245                 DEBUG(6,("final values: [%d], [%d]\n",
8246                         *r->out.value_needed, *r->out.data_needed));
8247
8248                 return WERR_OK;
8249         }
8250
8251         if (r->in.enum_index < count) {
8252                 val = &info[r->in.enum_index];
8253         }
8254
8255         if (val == NULL) {
8256                 /* out_value should default to "" or else NT4 has
8257                    problems unmarshalling the response */
8258
8259                 if (r->in.value_offered) {
8260                         *r->out.value_needed = 1;
8261                         r->out.value_name = talloc_strdup(r, "");
8262                         if (!r->out.value_name) {
8263                                 return WERR_NOMEM;
8264                         }
8265                 } else {
8266                         r->out.value_name = NULL;
8267                         *r->out.value_needed = 0;
8268                 }
8269
8270                 /* the data is counted in bytes */
8271
8272                 *r->out.data_needed = r->in.data_offered;
8273
8274                 result = WERR_NO_MORE_ITEMS;
8275         } else {
8276                 /*
8277                  * the value is:
8278                  * - counted in bytes in the request
8279                  * - counted in UNICODE chars in the max reply
8280                  * - counted in bytes in the real size
8281                  *
8282                  * take a pause *before* coding not *during* coding
8283                  */
8284
8285                 /* name */
8286                 if (r->in.value_offered) {
8287                         r->out.value_name = talloc_strdup(r, val->value_name);
8288                         if (!r->out.value_name) {
8289                                 return WERR_NOMEM;
8290                         }
8291                         *r->out.value_needed = val->value_name_len;
8292                 } else {
8293                         r->out.value_name = NULL;
8294                         *r->out.value_needed = 0;
8295                 }
8296
8297                 /* type */
8298
8299                 *r->out.type = val->type;
8300
8301                 /* data - counted in bytes */
8302
8303                 /*
8304                  * See the section "Dynamically Typed Query Parameters"
8305                  * in MS-RPRN.
8306                  */
8307
8308                 if (r->out.data && val->data && val->data->data &&
8309                                 val->data_length && r->in.data_offered) {
8310                         memcpy(r->out.data, val->data->data,
8311                                 MIN(val->data_length,r->in.data_offered));
8312                 }
8313
8314                 *r->out.data_needed = val->data_length;
8315
8316                 result = WERR_OK;
8317         }
8318
8319         return result;
8320 }
8321
8322 /****************************************************************
8323  _spoolss_SetPrinterData
8324 ****************************************************************/
8325
8326 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8327                                struct spoolss_SetPrinterData *r)
8328 {
8329         struct spoolss_SetPrinterDataEx r2;
8330
8331         r2.in.handle            = r->in.handle;
8332         r2.in.key_name          = "PrinterDriverData";
8333         r2.in.value_name        = r->in.value_name;
8334         r2.in.type              = r->in.type;
8335         r2.in.data              = r->in.data;
8336         r2.in.offered           = r->in.offered;
8337
8338         return _spoolss_SetPrinterDataEx(p, &r2);
8339 }
8340
8341 /****************************************************************
8342  _spoolss_ResetPrinter
8343 ****************************************************************/
8344
8345 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8346                              struct spoolss_ResetPrinter *r)
8347 {
8348         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8349         int             snum;
8350
8351         DEBUG(5,("_spoolss_ResetPrinter\n"));
8352
8353         /*
8354          * All we do is to check to see if the handle and queue is valid.
8355          * This call really doesn't mean anything to us because we only
8356          * support RAW printing.   --jerry
8357          */
8358
8359         if (!Printer) {
8360                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8361                         OUR_HANDLE(r->in.handle)));
8362                 return WERR_BADFID;
8363         }
8364
8365         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8366                 return WERR_BADFID;
8367
8368
8369         /* blindly return success */
8370         return WERR_OK;
8371 }
8372
8373 /****************************************************************
8374  _spoolss_DeletePrinterData
8375 ****************************************************************/
8376
8377 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8378                                   struct spoolss_DeletePrinterData *r)
8379 {
8380         struct spoolss_DeletePrinterDataEx r2;
8381
8382         r2.in.handle            = r->in.handle;
8383         r2.in.key_name          = "PrinterDriverData";
8384         r2.in.value_name        = r->in.value_name;
8385
8386         return _spoolss_DeletePrinterDataEx(p, &r2);
8387 }
8388
8389 /****************************************************************
8390  _spoolss_AddForm
8391 ****************************************************************/
8392
8393 WERROR _spoolss_AddForm(struct pipes_struct *p,
8394                         struct spoolss_AddForm *r)
8395 {
8396         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8397         int snum = -1;
8398         WERROR status = WERR_OK;
8399
8400         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8401
8402         DEBUG(5,("_spoolss_AddForm\n"));
8403
8404         if (!Printer) {
8405                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8406                         OUR_HANDLE(r->in.handle)));
8407                 return WERR_BADFID;
8408         }
8409
8410         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8411            and not a printer admin, then fail */
8412
8413         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8414             !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
8415             !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8416                                           p->server_info->info3->base.domain.string,
8417                                           NULL,
8418                                           p->server_info->ptok,
8419                                           lp_printer_admin(snum))) {
8420                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8421                 return WERR_ACCESS_DENIED;
8422         }
8423
8424         switch (form->flags) {
8425         case SPOOLSS_FORM_USER:
8426         case SPOOLSS_FORM_BUILTIN:
8427         case SPOOLSS_FORM_PRINTER:
8428                 break;
8429         default:
8430                 return WERR_INVALID_PARAM;
8431         }
8432
8433         status = winreg_printer_addform1(p->mem_ctx,
8434                                          get_server_info_system(),
8435                                          p->msg_ctx,
8436                                          form);
8437         if (!W_ERROR_IS_OK(status)) {
8438                 return status;
8439         }
8440
8441         /*
8442          * ChangeID must always be set if this is a printer
8443          */
8444         if (Printer->printer_type == SPLHND_PRINTER) {
8445                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8446                         return WERR_BADFID;
8447                 }
8448
8449                 status = winreg_printer_update_changeid(p->mem_ctx,
8450                                                         get_server_info_system(),
8451                                                         p->msg_ctx,
8452                                                         lp_const_servicename(snum));
8453                 if (!W_ERROR_IS_OK(status)) {
8454                         return status;
8455                 }
8456         }
8457
8458         return status;
8459 }
8460
8461 /****************************************************************
8462  _spoolss_DeleteForm
8463 ****************************************************************/
8464
8465 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8466                            struct spoolss_DeleteForm *r)
8467 {
8468         const char *form_name = r->in.form_name;
8469         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8470         int snum = -1;
8471         WERROR status = WERR_OK;
8472
8473         DEBUG(5,("_spoolss_DeleteForm\n"));
8474
8475         if (!Printer) {
8476                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8477                         OUR_HANDLE(r->in.handle)));
8478                 return WERR_BADFID;
8479         }
8480
8481         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8482             !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
8483             !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8484                                           p->server_info->info3->base.domain.string,
8485                                           NULL,
8486                                           p->server_info->ptok,
8487                                           lp_printer_admin(snum))) {
8488                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8489                 return WERR_ACCESS_DENIED;
8490         }
8491
8492         status = winreg_printer_deleteform1(p->mem_ctx,
8493                                             get_server_info_system(),
8494                                             p->msg_ctx,
8495                                             form_name);
8496         if (!W_ERROR_IS_OK(status)) {
8497                 return status;
8498         }
8499
8500         /*
8501          * ChangeID must always be set if this is a printer
8502          */
8503         if (Printer->printer_type == SPLHND_PRINTER) {
8504                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8505                         return WERR_BADFID;
8506                 }
8507
8508                 status = winreg_printer_update_changeid(p->mem_ctx,
8509                                                         get_server_info_system(),
8510                                                         p->msg_ctx,
8511                                                         lp_const_servicename(snum));
8512                 if (!W_ERROR_IS_OK(status)) {
8513                         return status;
8514                 }
8515         }
8516
8517         return status;
8518 }
8519
8520 /****************************************************************
8521  _spoolss_SetForm
8522 ****************************************************************/
8523
8524 WERROR _spoolss_SetForm(struct pipes_struct *p,
8525                         struct spoolss_SetForm *r)
8526 {
8527         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8528         const char *form_name = r->in.form_name;
8529         int snum = -1;
8530         WERROR status = WERR_OK;
8531
8532         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8533
8534         DEBUG(5,("_spoolss_SetForm\n"));
8535
8536         if (!Printer) {
8537                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8538                         OUR_HANDLE(r->in.handle)));
8539                 return WERR_BADFID;
8540         }
8541
8542         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8543            and not a printer admin, then fail */
8544
8545         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8546              !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
8547              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8548                                           p->server_info->info3->base.domain.string,
8549                                           NULL,
8550                                           p->server_info->ptok,
8551                                           lp_printer_admin(snum))) {
8552                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8553                 return WERR_ACCESS_DENIED;
8554         }
8555
8556         status = winreg_printer_setform1(p->mem_ctx,
8557                                          get_server_info_system(),
8558                                          p->msg_ctx,
8559                                          form_name,
8560                                          form);
8561         if (!W_ERROR_IS_OK(status)) {
8562                 return status;
8563         }
8564
8565         /*
8566          * ChangeID must always be set if this is a printer
8567          */
8568         if (Printer->printer_type == SPLHND_PRINTER) {
8569                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8570                         return WERR_BADFID;
8571                 }
8572
8573                 status = winreg_printer_update_changeid(p->mem_ctx,
8574                                                         get_server_info_system(),
8575                                                         p->msg_ctx,
8576                                                         lp_const_servicename(snum));
8577                 if (!W_ERROR_IS_OK(status)) {
8578                         return status;
8579                 }
8580         }
8581
8582         return status;
8583 }
8584
8585 /****************************************************************************
8586  fill_print_processor1
8587 ****************************************************************************/
8588
8589 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8590                                     struct spoolss_PrintProcessorInfo1 *r,
8591                                     const char *print_processor_name)
8592 {
8593         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8594         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8595
8596         return WERR_OK;
8597 }
8598
8599 /****************************************************************************
8600  enumprintprocessors level 1.
8601 ****************************************************************************/
8602
8603 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8604                                           union spoolss_PrintProcessorInfo **info_p,
8605                                           uint32_t *count)
8606 {
8607         union spoolss_PrintProcessorInfo *info;
8608         WERROR result;
8609
8610         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8611         W_ERROR_HAVE_NO_MEMORY(info);
8612
8613         *count = 1;
8614
8615         result = fill_print_processor1(info, &info[0].info1, "winprint");
8616         if (!W_ERROR_IS_OK(result)) {
8617                 goto out;
8618         }
8619
8620  out:
8621         if (!W_ERROR_IS_OK(result)) {
8622                 TALLOC_FREE(info);
8623                 *count = 0;
8624                 return result;
8625         }
8626
8627         *info_p = info;
8628
8629         return WERR_OK;
8630 }
8631
8632 /****************************************************************
8633  _spoolss_EnumPrintProcessors
8634 ****************************************************************/
8635
8636 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8637                                     struct spoolss_EnumPrintProcessors *r)
8638 {
8639         WERROR result;
8640
8641         /* that's an [in out] buffer */
8642
8643         if (!r->in.buffer && (r->in.offered != 0)) {
8644                 return WERR_INVALID_PARAM;
8645         }
8646
8647         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8648
8649         /*
8650          * Enumerate the print processors ...
8651          *
8652          * Just reply with "winprint", to keep NT happy
8653          * and I can use my nice printer checker.
8654          */
8655
8656         *r->out.count = 0;
8657         *r->out.needed = 0;
8658         *r->out.info = NULL;
8659
8660         if (!get_short_archi(r->in.environment)) {
8661                 return WERR_INVALID_ENVIRONMENT;
8662         }
8663
8664         switch (r->in.level) {
8665         case 1:
8666                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8667                                                      r->out.count);
8668                 break;
8669         default:
8670                 return WERR_UNKNOWN_LEVEL;
8671         }
8672
8673         if (!W_ERROR_IS_OK(result)) {
8674                 return result;
8675         }
8676
8677         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8678                                                      spoolss_EnumPrintProcessors,
8679                                                      *r->out.info, r->in.level,
8680                                                      *r->out.count);
8681         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8682         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8683
8684         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8685 }
8686
8687 /****************************************************************************
8688  fill_printprocdatatype1
8689 ****************************************************************************/
8690
8691 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8692                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8693                                       const char *name_array)
8694 {
8695         r->name_array = talloc_strdup(mem_ctx, name_array);
8696         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8697
8698         return WERR_OK;
8699 }
8700
8701 /****************************************************************************
8702  enumprintprocdatatypes level 1.
8703 ****************************************************************************/
8704
8705 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8706                                              union spoolss_PrintProcDataTypesInfo **info_p,
8707                                              uint32_t *count)
8708 {
8709         WERROR result;
8710         union spoolss_PrintProcDataTypesInfo *info;
8711
8712         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8713         W_ERROR_HAVE_NO_MEMORY(info);
8714
8715         *count = 1;
8716
8717         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8718         if (!W_ERROR_IS_OK(result)) {
8719                 goto out;
8720         }
8721
8722  out:
8723         if (!W_ERROR_IS_OK(result)) {
8724                 TALLOC_FREE(info);
8725                 *count = 0;
8726                 return result;
8727         }
8728
8729         *info_p = info;
8730
8731         return WERR_OK;
8732 }
8733
8734 /****************************************************************
8735  _spoolss_EnumPrintProcDataTypes
8736 ****************************************************************/
8737
8738 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8739                                        struct spoolss_EnumPrintProcDataTypes *r)
8740 {
8741         WERROR result;
8742
8743         /* that's an [in out] buffer */
8744
8745         if (!r->in.buffer && (r->in.offered != 0)) {
8746                 return WERR_INVALID_PARAM;
8747         }
8748
8749         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8750
8751         *r->out.count = 0;
8752         *r->out.needed = 0;
8753         *r->out.info = NULL;
8754
8755         if (r->in.print_processor_name == NULL ||
8756             !strequal(r->in.print_processor_name, "winprint")) {
8757                 return WERR_UNKNOWN_PRINTPROCESSOR;
8758         }
8759
8760         switch (r->in.level) {
8761         case 1:
8762                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8763                                                         r->out.count);
8764                 break;
8765         default:
8766                 return WERR_UNKNOWN_LEVEL;
8767         }
8768
8769         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8770                                                      spoolss_EnumPrintProcDataTypes, 
8771                                                      *r->out.info, r->in.level,
8772                                                      *r->out.count);
8773         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8774         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8775
8776         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8777 }
8778
8779 /****************************************************************************
8780  fill_monitor_1
8781 ****************************************************************************/
8782
8783 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8784                              struct spoolss_MonitorInfo1 *r,
8785                              const char *monitor_name)
8786 {
8787         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8788         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8789
8790         return WERR_OK;
8791 }
8792
8793 /****************************************************************************
8794  fill_monitor_2
8795 ****************************************************************************/
8796
8797 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8798                              struct spoolss_MonitorInfo2 *r,
8799                              const char *monitor_name,
8800                              const char *environment,
8801                              const char *dll_name)
8802 {
8803         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8804         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8805         r->environment                  = talloc_strdup(mem_ctx, environment);
8806         W_ERROR_HAVE_NO_MEMORY(r->environment);
8807         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8808         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8809
8810         return WERR_OK;
8811 }
8812
8813 /****************************************************************************
8814  enumprintmonitors level 1.
8815 ****************************************************************************/
8816
8817 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8818                                         union spoolss_MonitorInfo **info_p,
8819                                         uint32_t *count)
8820 {
8821         union spoolss_MonitorInfo *info;
8822         WERROR result = WERR_OK;
8823
8824         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8825         W_ERROR_HAVE_NO_MEMORY(info);
8826
8827         *count = 2;
8828
8829         result = fill_monitor_1(info, &info[0].info1,
8830                                 SPL_LOCAL_PORT);
8831         if (!W_ERROR_IS_OK(result)) {
8832                 goto out;
8833         }
8834
8835         result = fill_monitor_1(info, &info[1].info1,
8836                                 SPL_TCPIP_PORT);
8837         if (!W_ERROR_IS_OK(result)) {
8838                 goto out;
8839         }
8840
8841 out:
8842         if (!W_ERROR_IS_OK(result)) {
8843                 TALLOC_FREE(info);
8844                 *count = 0;
8845                 return result;
8846         }
8847
8848         *info_p = info;
8849
8850         return WERR_OK;
8851 }
8852
8853 /****************************************************************************
8854  enumprintmonitors level 2.
8855 ****************************************************************************/
8856
8857 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8858                                         union spoolss_MonitorInfo **info_p,
8859                                         uint32_t *count)
8860 {
8861         union spoolss_MonitorInfo *info;
8862         WERROR result = WERR_OK;
8863
8864         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8865         W_ERROR_HAVE_NO_MEMORY(info);
8866
8867         *count = 2;
8868
8869         result = fill_monitor_2(info, &info[0].info2,
8870                                 SPL_LOCAL_PORT,
8871                                 "Windows NT X86", /* FIXME */
8872                                 "localmon.dll");
8873         if (!W_ERROR_IS_OK(result)) {
8874                 goto out;
8875         }
8876
8877         result = fill_monitor_2(info, &info[1].info2,
8878                                 SPL_TCPIP_PORT,
8879                                 "Windows NT X86", /* FIXME */
8880                                 "tcpmon.dll");
8881         if (!W_ERROR_IS_OK(result)) {
8882                 goto out;
8883         }
8884
8885 out:
8886         if (!W_ERROR_IS_OK(result)) {
8887                 TALLOC_FREE(info);
8888                 *count = 0;
8889                 return result;
8890         }
8891
8892         *info_p = info;
8893
8894         return WERR_OK;
8895 }
8896
8897 /****************************************************************
8898  _spoolss_EnumMonitors
8899 ****************************************************************/
8900
8901 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8902                              struct spoolss_EnumMonitors *r)
8903 {
8904         WERROR result;
8905
8906         /* that's an [in out] buffer */
8907
8908         if (!r->in.buffer && (r->in.offered != 0)) {
8909                 return WERR_INVALID_PARAM;
8910         }
8911
8912         DEBUG(5,("_spoolss_EnumMonitors\n"));
8913
8914         /*
8915          * Enumerate the print monitors ...
8916          *
8917          * Just reply with "Local Port", to keep NT happy
8918          * and I can use my nice printer checker.
8919          */
8920
8921         *r->out.count = 0;
8922         *r->out.needed = 0;
8923         *r->out.info = NULL;
8924
8925         switch (r->in.level) {
8926         case 1:
8927                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8928                                                    r->out.count);
8929                 break;
8930         case 2:
8931                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8932                                                    r->out.count);
8933                 break;
8934         default:
8935                 return WERR_UNKNOWN_LEVEL;
8936         }
8937
8938         if (!W_ERROR_IS_OK(result)) {
8939                 return result;
8940         }
8941
8942         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8943                                                      spoolss_EnumMonitors, 
8944                                                      *r->out.info, r->in.level,
8945                                                      *r->out.count);
8946         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8947         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8948
8949         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8950 }
8951
8952 /****************************************************************************
8953 ****************************************************************************/
8954
8955 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8956                              const print_queue_struct *queue,
8957                              int count, int snum,
8958                              struct spoolss_PrinterInfo2 *pinfo2,
8959                              uint32_t jobid,
8960                              struct spoolss_JobInfo1 *r)
8961 {
8962         int i = 0;
8963         bool found = false;
8964
8965         for (i=0; i<count; i++) {
8966                 if (queue[i].job == (int)jobid) {
8967                         found = true;
8968                         break;
8969                 }
8970         }
8971
8972         if (found == false) {
8973                 /* NT treats not found as bad param... yet another bad choice */
8974                 return WERR_INVALID_PARAM;
8975         }
8976
8977         return fill_job_info1(mem_ctx,
8978                               r,
8979                               &queue[i],
8980                               i,
8981                               snum,
8982                               pinfo2);
8983 }
8984
8985 /****************************************************************************
8986 ****************************************************************************/
8987
8988 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8989                              const print_queue_struct *queue,
8990                              int count, int snum,
8991                              struct spoolss_PrinterInfo2 *pinfo2,
8992                              uint32_t jobid,
8993                              struct spoolss_JobInfo2 *r)
8994 {
8995         int i = 0;
8996         bool found = false;
8997         struct spoolss_DeviceMode *devmode;
8998         WERROR result;
8999
9000         for (i=0; i<count; i++) {
9001                 if (queue[i].job == (int)jobid) {
9002                         found = true;
9003                         break;
9004                 }
9005         }
9006
9007         if (found == false) {
9008                 /* NT treats not found as bad param... yet another bad
9009                    choice */
9010                 return WERR_INVALID_PARAM;
9011         }
9012
9013         /*
9014          * if the print job does not have a DEVMODE associated with it,
9015          * just use the one for the printer. A NULL devicemode is not
9016          *  a failure condition
9017          */
9018
9019         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9020         if (!devmode) {
9021                 result = spoolss_create_default_devmode(mem_ctx,
9022                                                 pinfo2->printername,
9023                                                 &devmode);
9024                 if (!W_ERROR_IS_OK(result)) {
9025                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9026                         return result;
9027                 }
9028         }
9029
9030         return fill_job_info2(mem_ctx,
9031                               r,
9032                               &queue[i],
9033                               i,
9034                               snum,
9035                               pinfo2,
9036                               devmode);
9037 }
9038
9039 /****************************************************************
9040  _spoolss_GetJob
9041 ****************************************************************/
9042
9043 WERROR _spoolss_GetJob(struct pipes_struct *p,
9044                        struct spoolss_GetJob *r)
9045 {
9046         WERROR result = WERR_OK;
9047         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9048         int snum;
9049         int count;
9050         print_queue_struct      *queue = NULL;
9051         print_status_struct prt_status;
9052
9053         /* that's an [in out] buffer */
9054
9055         if (!r->in.buffer && (r->in.offered != 0)) {
9056                 return WERR_INVALID_PARAM;
9057         }
9058
9059         DEBUG(5,("_spoolss_GetJob\n"));
9060
9061         *r->out.needed = 0;
9062
9063         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9064                 return WERR_BADFID;
9065         }
9066
9067         result = winreg_get_printer(p->mem_ctx,
9068                                     get_server_info_system(),
9069                                     p->msg_ctx,
9070                                     lp_const_servicename(snum),
9071                                     &pinfo2);
9072         if (!W_ERROR_IS_OK(result)) {
9073                 return result;
9074         }
9075
9076         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9077
9078         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9079                      count, prt_status.status, prt_status.message));
9080
9081         switch (r->in.level) {
9082         case 1:
9083                 result = getjob_level_1(p->mem_ctx,
9084                                         queue, count, snum, pinfo2,
9085                                         r->in.job_id, &r->out.info->info1);
9086                 break;
9087         case 2:
9088                 result = getjob_level_2(p->mem_ctx,
9089                                         queue, count, snum, pinfo2,
9090                                         r->in.job_id, &r->out.info->info2);
9091                 break;
9092         default:
9093                 result = WERR_UNKNOWN_LEVEL;
9094                 break;
9095         }
9096
9097         SAFE_FREE(queue);
9098         TALLOC_FREE(pinfo2);
9099
9100         if (!W_ERROR_IS_OK(result)) {
9101                 TALLOC_FREE(r->out.info);
9102                 return result;
9103         }
9104
9105         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9106                                                                                    r->in.level);
9107         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9108
9109         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9110 }
9111
9112 /****************************************************************
9113  _spoolss_GetPrinterDataEx
9114 ****************************************************************/
9115
9116 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9117                                  struct spoolss_GetPrinterDataEx *r)
9118 {
9119
9120         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9121         const char *printer;
9122         int                     snum = 0;
9123         WERROR result = WERR_OK;
9124         DATA_BLOB blob;
9125         enum winreg_Type val_type;
9126         uint8_t *val_data;
9127         uint32_t val_size;
9128
9129
9130         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9131
9132         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9133                 r->in.key_name, r->in.value_name));
9134
9135         /* in case of problem, return some default values */
9136
9137         *r->out.needed  = 0;
9138         *r->out.type    = REG_NONE;
9139
9140         if (!Printer) {
9141                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9142                         OUR_HANDLE(r->in.handle)));
9143                 result = WERR_BADFID;
9144                 goto done;
9145         }
9146
9147         /* Is the handle to a printer or to the server? */
9148
9149         if (Printer->printer_type == SPLHND_SERVER) {
9150
9151                 union spoolss_PrinterData data;
9152
9153                 result = getprinterdata_printer_server(p->mem_ctx,
9154                                                        r->in.value_name,
9155                                                        r->out.type,
9156                                                        &data);
9157                 if (!W_ERROR_IS_OK(result)) {
9158                         return result;
9159                 }
9160
9161                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9162                                                   *r->out.type, &data);
9163                 if (!W_ERROR_IS_OK(result)) {
9164                         return result;
9165                 }
9166
9167                 *r->out.needed = blob.length;
9168
9169                 if (r->in.offered >= *r->out.needed) {
9170                         memcpy(r->out.data, blob.data, blob.length);
9171                 }
9172
9173                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9174         }
9175
9176         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9177                 return WERR_BADFID;
9178         }
9179         printer = lp_const_servicename(snum);
9180
9181         /* check to see if the keyname is valid */
9182         if (!strlen(r->in.key_name)) {
9183                 return WERR_INVALID_PARAM;
9184         }
9185
9186         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9187         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9188             strequal(r->in.value_name, "ChangeId")) {
9189                 *r->out.type = REG_DWORD;
9190                 *r->out.needed = 4;
9191                 if (r->in.offered >= *r->out.needed) {
9192                         uint32_t changeid = 0;
9193
9194                         result = winreg_printer_get_changeid(p->mem_ctx,
9195                                                              get_server_info_system(),
9196                                                              p->msg_ctx,
9197                                                              printer,
9198                                                              &changeid);
9199                         if (!W_ERROR_IS_OK(result)) {
9200                                 return result;
9201                         }
9202
9203                         SIVAL(r->out.data, 0, changeid);
9204                         result = WERR_OK;
9205                 }
9206                 goto done;
9207         }
9208
9209         result = winreg_get_printer_dataex(p->mem_ctx,
9210                                            get_server_info_system(),
9211                                            p->msg_ctx,
9212                                            printer,
9213                                            r->in.key_name,
9214                                            r->in.value_name,
9215                                            &val_type,
9216                                            &val_data,
9217                                            &val_size);
9218         if (!W_ERROR_IS_OK(result)) {
9219                 return result;
9220         }
9221
9222         *r->out.needed = val_size;
9223         *r->out.type = val_type;
9224
9225         if (r->in.offered >= *r->out.needed) {
9226                 memcpy(r->out.data, val_data, val_size);
9227         }
9228
9229  done:
9230         /* retain type when returning WERR_MORE_DATA */
9231         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9232
9233         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9234 }
9235
9236 /****************************************************************
9237  _spoolss_SetPrinterDataEx
9238 ****************************************************************/
9239
9240 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9241                                  struct spoolss_SetPrinterDataEx *r)
9242 {
9243         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9244         int                     snum = 0;
9245         WERROR                  result = WERR_OK;
9246         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9247         char                    *oid_string;
9248
9249         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9250
9251         /* From MSDN documentation of SetPrinterDataEx: pass request to
9252            SetPrinterData if key is "PrinterDriverData" */
9253
9254         if (!Printer) {
9255                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9256                         OUR_HANDLE(r->in.handle)));
9257                 return WERR_BADFID;
9258         }
9259
9260         if (Printer->printer_type == SPLHND_SERVER) {
9261                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9262                         "Not implemented for server handles yet\n"));
9263                 return WERR_INVALID_PARAM;
9264         }
9265
9266         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9267                 return WERR_BADFID;
9268         }
9269
9270         /*
9271          * Access check : NT returns "access denied" if you make a
9272          * SetPrinterData call without the necessary privildge.
9273          * we were originally returning OK if nothing changed
9274          * which made Win2k issue **a lot** of SetPrinterData
9275          * when connecting to a printer  --jerry
9276          */
9277
9278         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9279                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9280                         "change denied by handle access permissions\n"));
9281                 return WERR_ACCESS_DENIED;
9282         }
9283
9284         result = winreg_get_printer(Printer,
9285                                     get_server_info_system(),
9286                                     p->msg_ctx,
9287                                     lp_servicename(snum),
9288                                     &pinfo2);
9289         if (!W_ERROR_IS_OK(result)) {
9290                 return result;
9291         }
9292
9293         /* check for OID in valuename */
9294
9295         oid_string = strchr(r->in.value_name, ',');
9296         if (oid_string) {
9297                 *oid_string = '\0';
9298                 oid_string++;
9299         }
9300
9301         /* save the registry data */
9302
9303         result = winreg_set_printer_dataex(p->mem_ctx,
9304                                            get_server_info_system(),
9305                                            p->msg_ctx,
9306                                            pinfo2->sharename,
9307                                            r->in.key_name,
9308                                            r->in.value_name,
9309                                            r->in.type,
9310                                            r->in.data,
9311                                            r->in.offered);
9312
9313         if (W_ERROR_IS_OK(result)) {
9314                 /* save the OID if one was specified */
9315                 if (oid_string) {
9316                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9317                                 r->in.key_name, SPOOL_OID_KEY);
9318                         if (!str) {
9319                                 result = WERR_NOMEM;
9320                                 goto done;
9321                         }
9322
9323                         /*
9324                          * I'm not checking the status here on purpose.  Don't know
9325                          * if this is right, but I'm returning the status from the
9326                          * previous set_printer_dataex() call.  I have no idea if
9327                          * this is right.    --jerry
9328                          */
9329                         winreg_set_printer_dataex(p->mem_ctx,
9330                                                   get_server_info_system(),
9331                                                   p->msg_ctx,
9332                                                   pinfo2->sharename,
9333                                                   str,
9334                                                   r->in.value_name,
9335                                                   REG_SZ,
9336                                                   (uint8_t *) oid_string,
9337                                                   strlen(oid_string) + 1);
9338                 }
9339
9340                 result = winreg_printer_update_changeid(p->mem_ctx,
9341                                                         get_server_info_system(),
9342                                                         p->msg_ctx,
9343                                                         lp_const_servicename(snum));
9344
9345         }
9346
9347 done:
9348         talloc_free(pinfo2);
9349         return result;
9350 }
9351
9352 /****************************************************************
9353  _spoolss_DeletePrinterDataEx
9354 ****************************************************************/
9355
9356 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9357                                     struct spoolss_DeletePrinterDataEx *r)
9358 {
9359         const char *printer;
9360         int             snum=0;
9361         WERROR          status = WERR_OK;
9362         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9363
9364         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9365
9366         if (!Printer) {
9367                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9368                         "Invalid handle (%s:%u:%u).\n",
9369                         OUR_HANDLE(r->in.handle)));
9370                 return WERR_BADFID;
9371         }
9372
9373         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9374                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9375                         "printer properties change denied by handle\n"));
9376                 return WERR_ACCESS_DENIED;
9377         }
9378
9379         if (!r->in.value_name || !r->in.key_name) {
9380                 return WERR_NOMEM;
9381         }
9382
9383         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9384                 return WERR_BADFID;
9385         }
9386         printer = lp_const_servicename(snum);
9387
9388         status = winreg_delete_printer_dataex(p->mem_ctx,
9389                                               get_server_info_system(),
9390                                               p->msg_ctx,
9391                                               printer,
9392                                               r->in.key_name,
9393                                               r->in.value_name);
9394         if (W_ERROR_IS_OK(status)) {
9395                 status = winreg_printer_update_changeid(p->mem_ctx,
9396                                                         get_server_info_system(),
9397                                                         p->msg_ctx,
9398                                                         printer);
9399         }
9400
9401         return status;
9402 }
9403
9404 /****************************************************************
9405  _spoolss_EnumPrinterKey
9406 ****************************************************************/
9407
9408 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9409                                struct spoolss_EnumPrinterKey *r)
9410 {
9411         uint32_t        num_keys;
9412         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9413         int             snum = 0;
9414         WERROR          result = WERR_BADFILE;
9415         const char **array = NULL;
9416         DATA_BLOB blob;
9417
9418         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9419
9420         if (!Printer) {
9421                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9422                         OUR_HANDLE(r->in.handle)));
9423                 return WERR_BADFID;
9424         }
9425
9426         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9427                 return WERR_BADFID;
9428         }
9429
9430         result = winreg_enum_printer_key(p->mem_ctx,
9431                                          get_server_info_system(),
9432                                          p->msg_ctx,
9433                                          lp_const_servicename(snum),
9434                                          r->in.key_name,
9435                                          &num_keys,
9436                                          &array);
9437         if (!W_ERROR_IS_OK(result)) {
9438                 goto done;
9439         }
9440
9441         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9442                 result = WERR_NOMEM;
9443                 goto done;
9444         }
9445
9446         *r->out._ndr_size = r->in.offered / 2;
9447         *r->out.needed = blob.length;
9448
9449         if (r->in.offered < *r->out.needed) {
9450                 result = WERR_MORE_DATA;
9451         } else {
9452                 result = WERR_OK;
9453                 r->out.key_buffer->string_array = array;
9454         }
9455
9456  done:
9457         if (!W_ERROR_IS_OK(result)) {
9458                 TALLOC_FREE(array);
9459                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9460                         *r->out.needed = 0;
9461                 }
9462         }
9463
9464         return result;
9465 }
9466
9467 /****************************************************************
9468  _spoolss_DeletePrinterKey
9469 ****************************************************************/
9470
9471 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9472                                  struct spoolss_DeletePrinterKey *r)
9473 {
9474         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9475         int                     snum=0;
9476         WERROR                  status;
9477         const char *printer;
9478
9479         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9480
9481         if (!Printer) {
9482                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9483                         OUR_HANDLE(r->in.handle)));
9484                 return WERR_BADFID;
9485         }
9486
9487         /* if keyname == NULL, return error */
9488         if ( !r->in.key_name )
9489                 return WERR_INVALID_PARAM;
9490
9491         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9492                 return WERR_BADFID;
9493         }
9494
9495         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9496                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9497                         "printer properties change denied by handle\n"));
9498                 return WERR_ACCESS_DENIED;
9499         }
9500
9501         printer = lp_const_servicename(snum);
9502
9503         /* delete the key and all subkeys */
9504         status = winreg_delete_printer_key(p->mem_ctx,
9505                                            get_server_info_system(),
9506                                            p->msg_ctx,
9507                                            printer,
9508                                            r->in.key_name);
9509         if (W_ERROR_IS_OK(status)) {
9510                 status = winreg_printer_update_changeid(p->mem_ctx,
9511                                                         get_server_info_system(),
9512                                                         p->msg_ctx,
9513                                                         printer);
9514         }
9515
9516         return status;
9517 }
9518
9519 /****************************************************************
9520  _spoolss_EnumPrinterDataEx
9521 ****************************************************************/
9522
9523 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9524                                   struct spoolss_EnumPrinterDataEx *r)
9525 {
9526         uint32_t        count = 0;
9527         struct spoolss_PrinterEnumValues *info = NULL;
9528         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9529         int             snum;
9530         WERROR          result;
9531
9532         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9533
9534         *r->out.count = 0;
9535         *r->out.needed = 0;
9536         *r->out.info = NULL;
9537
9538         if (!Printer) {
9539                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9540                         OUR_HANDLE(r->in.handle)));
9541                 return WERR_BADFID;
9542         }
9543
9544         /*
9545          * first check for a keyname of NULL or "".  Win2k seems to send
9546          * this a lot and we should send back WERR_INVALID_PARAM
9547          * no need to spend time looking up the printer in this case.
9548          * --jerry
9549          */
9550
9551         if (!strlen(r->in.key_name)) {
9552                 result = WERR_INVALID_PARAM;
9553                 goto done;
9554         }
9555
9556         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9557                 return WERR_BADFID;
9558         }
9559
9560         /* now look for a match on the key name */
9561         result = winreg_enum_printer_dataex(p->mem_ctx,
9562                                             get_server_info_system(),
9563                                             p->msg_ctx,
9564                                             lp_const_servicename(snum),
9565                                             r->in.key_name,
9566                                             &count,
9567                                             &info);
9568         if (!W_ERROR_IS_OK(result)) {
9569                 goto done;
9570         }
9571
9572 #if 0 /* FIXME - gd */
9573         /* housekeeping information in the reply */
9574
9575         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9576          * the hand marshalled container size is a multiple
9577          * of 4 bytes for RPC alignment.
9578          */
9579
9580         if (needed % 4) {
9581                 needed += 4-(needed % 4);
9582         }
9583 #endif
9584         *r->out.count   = count;
9585         *r->out.info    = info;
9586
9587  done:
9588         if (!W_ERROR_IS_OK(result)) {
9589                 return result;
9590         }
9591
9592         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9593                                                spoolss_EnumPrinterDataEx, 
9594                                                *r->out.info,
9595                                                *r->out.count);
9596         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9597         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9598
9599         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9600 }
9601
9602 /****************************************************************************
9603 ****************************************************************************/
9604
9605 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9606                                                  const char *servername,
9607                                                  const char *environment,
9608                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9609 {
9610         WERROR werr;
9611         char *path = NULL;
9612
9613         werr = compose_spoolss_server_path(mem_ctx,
9614                                            servername,
9615                                            environment,
9616                                            SPOOLSS_PRTPROCS_PATH,
9617                                            &path);
9618         if (!W_ERROR_IS_OK(werr)) {
9619                 return werr;
9620         }
9621
9622         DEBUG(4,("print processor directory: [%s]\n", path));
9623
9624         r->directory_name = path;
9625
9626         return WERR_OK;
9627 }
9628
9629 /****************************************************************
9630  _spoolss_GetPrintProcessorDirectory
9631 ****************************************************************/
9632
9633 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9634                                            struct spoolss_GetPrintProcessorDirectory *r)
9635 {
9636         WERROR result;
9637         char *prnproc_share = NULL;
9638         bool prnproc_share_exists = false;
9639         int snum;
9640
9641         /* that's an [in out] buffer */
9642
9643         if (!r->in.buffer && (r->in.offered != 0)) {
9644                 return WERR_INVALID_PARAM;
9645         }
9646
9647         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9648                 r->in.level));
9649
9650         *r->out.needed = 0;
9651
9652         /* r->in.level is ignored */
9653
9654         /* We always should reply with a local print processor directory so that
9655          * users are not forced to have a [prnproc$] share on the Samba spoolss
9656          * server, if users decide to do so, lets announce it though - Guenther */
9657
9658         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9659         if (!prnproc_share) {
9660                 return WERR_NOMEM;
9661         }
9662         if (snum != -1) {
9663                 prnproc_share_exists = true;
9664         }
9665
9666         result = getprintprocessordirectory_level_1(p->mem_ctx,
9667                                                     prnproc_share_exists ? r->in.server : NULL,
9668                                                     r->in.environment,
9669                                                     &r->out.info->info1);
9670         if (!W_ERROR_IS_OK(result)) {
9671                 TALLOC_FREE(r->out.info);
9672                 return result;
9673         }
9674
9675         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9676                                                                                    r->out.info, r->in.level);
9677         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9678
9679         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9680 }
9681
9682 /*******************************************************************
9683  ********************************************************************/
9684
9685 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9686                                const char *dllname)
9687 {
9688         enum ndr_err_code ndr_err;
9689         struct spoolss_MonitorUi ui;
9690
9691         ui.dll_name = dllname;
9692
9693         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9694                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9695         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9696                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9697         }
9698         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9699 }
9700
9701 /*******************************************************************
9702  Streams the monitor UI DLL name in UNICODE
9703 *******************************************************************/
9704
9705 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9706                                struct security_token *token, DATA_BLOB *in,
9707                                DATA_BLOB *out, uint32_t *needed)
9708 {
9709         const char *dllname = "tcpmonui.dll";
9710
9711         *needed = (strlen(dllname)+1) * 2;
9712
9713         if (out->length < *needed) {
9714                 return WERR_INSUFFICIENT_BUFFER;
9715         }
9716
9717         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9718                 return WERR_NOMEM;
9719         }
9720
9721         return WERR_OK;
9722 }
9723
9724 /*******************************************************************
9725  ********************************************************************/
9726
9727 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9728                              struct spoolss_PortData1 *port1,
9729                              const DATA_BLOB *buf)
9730 {
9731         enum ndr_err_code ndr_err;
9732         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9733                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9734         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9735                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9736         }
9737         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9738 }
9739
9740 /*******************************************************************
9741  ********************************************************************/
9742
9743 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9744                              struct spoolss_PortData2 *port2,
9745                              const DATA_BLOB *buf)
9746 {
9747         enum ndr_err_code ndr_err;
9748         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9749                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9750         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9751                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9752         }
9753         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9754 }
9755
9756 /*******************************************************************
9757  Create a new TCP/IP port
9758 *******************************************************************/
9759
9760 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9761                              struct security_token *token, DATA_BLOB *in,
9762                              DATA_BLOB *out, uint32_t *needed)
9763 {
9764         struct spoolss_PortData1 port1;
9765         struct spoolss_PortData2 port2;
9766         char *device_uri = NULL;
9767         uint32_t version;
9768
9769         const char *portname;
9770         const char *hostaddress;
9771         const char *queue;
9772         uint32_t port_number;
9773         uint32_t protocol;
9774
9775         /* peek for spoolss_PortData version */
9776
9777         if (!in || (in->length < (128 + 4))) {
9778                 return WERR_GENERAL_FAILURE;
9779         }
9780
9781         version = IVAL(in->data, 128);
9782
9783         switch (version) {
9784                 case 1:
9785                         ZERO_STRUCT(port1);
9786
9787                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9788                                 return WERR_NOMEM;
9789                         }
9790
9791                         portname        = port1.portname;
9792                         hostaddress     = port1.hostaddress;
9793                         queue           = port1.queue;
9794                         protocol        = port1.protocol;
9795                         port_number     = port1.port_number;
9796
9797                         break;
9798                 case 2:
9799                         ZERO_STRUCT(port2);
9800
9801                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9802                                 return WERR_NOMEM;
9803                         }
9804
9805                         portname        = port2.portname;
9806                         hostaddress     = port2.hostaddress;
9807                         queue           = port2.queue;
9808                         protocol        = port2.protocol;
9809                         port_number     = port2.port_number;
9810
9811                         break;
9812                 default:
9813                         DEBUG(1,("xcvtcp_addport: "
9814                                 "unknown version of port_data: %d\n", version));
9815                         return WERR_UNKNOWN_PORT;
9816         }
9817
9818         /* create the device URI and call the add_port_hook() */
9819
9820         switch (protocol) {
9821         case PROTOCOL_RAWTCP_TYPE:
9822                 device_uri = talloc_asprintf(mem_ctx,
9823                                 "socket://%s:%d/", hostaddress,
9824                                 port_number);
9825                 break;
9826
9827         case PROTOCOL_LPR_TYPE:
9828                 device_uri = talloc_asprintf(mem_ctx,
9829                         "lpr://%s/%s", hostaddress, queue );
9830                 break;
9831
9832         default:
9833                 return WERR_UNKNOWN_PORT;
9834         }
9835
9836         if (!device_uri) {
9837                 return WERR_NOMEM;
9838         }
9839
9840         return add_port_hook(mem_ctx, token, portname, device_uri);
9841 }
9842
9843 /*******************************************************************
9844 *******************************************************************/
9845
9846 struct xcv_api_table xcvtcp_cmds[] = {
9847         { "MonitorUI",  xcvtcp_monitorui },
9848         { "AddPort",    xcvtcp_addport},
9849         { NULL,         NULL }
9850 };
9851
9852 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9853                                      struct security_token *token, const char *command,
9854                                      DATA_BLOB *inbuf,
9855                                      DATA_BLOB *outbuf,
9856                                      uint32_t *needed )
9857 {
9858         int i;
9859
9860         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9861
9862         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9863                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9864                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9865         }
9866
9867         return WERR_BADFUNC;
9868 }
9869
9870 /*******************************************************************
9871 *******************************************************************/
9872 #if 0   /* don't support management using the "Local Port" monitor */
9873
9874 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9875                                  struct security_token *token, DATA_BLOB *in,
9876                                  DATA_BLOB *out, uint32_t *needed)
9877 {
9878         const char *dllname = "localui.dll";
9879
9880         *needed = (strlen(dllname)+1) * 2;
9881
9882         if (out->length < *needed) {
9883                 return WERR_INSUFFICIENT_BUFFER;
9884         }
9885
9886         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9887                 return WERR_NOMEM;
9888         }
9889
9890         return WERR_OK;
9891 }
9892
9893 /*******************************************************************
9894 *******************************************************************/
9895
9896 struct xcv_api_table xcvlocal_cmds[] = {
9897         { "MonitorUI",  xcvlocal_monitorui },
9898         { NULL,         NULL }
9899 };
9900 #else
9901 struct xcv_api_table xcvlocal_cmds[] = {
9902         { NULL,         NULL }
9903 };
9904 #endif
9905
9906
9907
9908 /*******************************************************************
9909 *******************************************************************/
9910
9911 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9912                                        struct security_token *token, const char *command,
9913                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9914                                        uint32_t *needed)
9915 {
9916         int i;
9917
9918         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9919
9920         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9921                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9922                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9923         }
9924         return WERR_BADFUNC;
9925 }
9926
9927 /****************************************************************
9928  _spoolss_XcvData
9929 ****************************************************************/
9930
9931 WERROR _spoolss_XcvData(struct pipes_struct *p,
9932                         struct spoolss_XcvData *r)
9933 {
9934         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9935         DATA_BLOB out_data = data_blob_null;
9936         WERROR werror;
9937
9938         if (!Printer) {
9939                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9940                         OUR_HANDLE(r->in.handle)));
9941                 return WERR_BADFID;
9942         }
9943
9944         /* Has to be a handle to the TCP/IP port monitor */
9945
9946         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9947                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9948                 return WERR_BADFID;
9949         }
9950
9951         /* requires administrative access to the server */
9952
9953         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9954                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9955                 return WERR_ACCESS_DENIED;
9956         }
9957
9958         /* Allocate the outgoing buffer */
9959
9960         if (r->in.out_data_size) {
9961                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9962                 if (out_data.data == NULL) {
9963                         return WERR_NOMEM;
9964                 }
9965         }
9966
9967         switch ( Printer->printer_type ) {
9968         case SPLHND_PORTMON_TCP:
9969                 werror = process_xcvtcp_command(p->mem_ctx,
9970                                                 p->server_info->ptok,
9971                                                 r->in.function_name,
9972                                                 &r->in.in_data, &out_data,
9973                                                 r->out.needed);
9974                 break;
9975         case SPLHND_PORTMON_LOCAL:
9976                 werror = process_xcvlocal_command(p->mem_ctx,
9977                                                   p->server_info->ptok,
9978                                                   r->in.function_name,
9979                                                   &r->in.in_data, &out_data,
9980                                                   r->out.needed);
9981                 break;
9982         default:
9983                 werror = WERR_INVALID_PRINT_MONITOR;
9984         }
9985
9986         if (!W_ERROR_IS_OK(werror)) {
9987                 return werror;
9988         }
9989
9990         *r->out.status_code = 0;
9991
9992         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9993                 memcpy(r->out.out_data, out_data.data,
9994                         MIN(r->in.out_data_size, out_data.length));
9995         }
9996
9997         return WERR_OK;
9998 }
9999
10000 /****************************************************************
10001  _spoolss_AddPrintProcessor
10002 ****************************************************************/
10003
10004 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10005                                   struct spoolss_AddPrintProcessor *r)
10006 {
10007         /* for now, just indicate success and ignore the add.  We'll
10008            automatically set the winprint processor for printer
10009            entries later.  Used to debug the LexMark Optra S 1855 PCL
10010            driver --jerry */
10011
10012         return WERR_OK;
10013 }
10014
10015 /****************************************************************
10016  _spoolss_AddPort
10017 ****************************************************************/
10018
10019 WERROR _spoolss_AddPort(struct pipes_struct *p,
10020                         struct spoolss_AddPort *r)
10021 {
10022         /* do what w2k3 does */
10023
10024         return WERR_NOT_SUPPORTED;
10025 }
10026
10027 /****************************************************************
10028  _spoolss_GetPrinterDriver
10029 ****************************************************************/
10030
10031 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10032                                  struct spoolss_GetPrinterDriver *r)
10033 {
10034         p->rng_fault_state = true;
10035         return WERR_NOT_SUPPORTED;
10036 }
10037
10038 /****************************************************************
10039  _spoolss_ReadPrinter
10040 ****************************************************************/
10041
10042 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10043                             struct spoolss_ReadPrinter *r)
10044 {
10045         p->rng_fault_state = true;
10046         return WERR_NOT_SUPPORTED;
10047 }
10048
10049 /****************************************************************
10050  _spoolss_WaitForPrinterChange
10051 ****************************************************************/
10052
10053 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10054                                      struct spoolss_WaitForPrinterChange *r)
10055 {
10056         p->rng_fault_state = true;
10057         return WERR_NOT_SUPPORTED;
10058 }
10059
10060 /****************************************************************
10061  _spoolss_ConfigurePort
10062 ****************************************************************/
10063
10064 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10065                               struct spoolss_ConfigurePort *r)
10066 {
10067         p->rng_fault_state = true;
10068         return WERR_NOT_SUPPORTED;
10069 }
10070
10071 /****************************************************************
10072  _spoolss_DeletePort
10073 ****************************************************************/
10074
10075 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10076                            struct spoolss_DeletePort *r)
10077 {
10078         p->rng_fault_state = true;
10079         return WERR_NOT_SUPPORTED;
10080 }
10081
10082 /****************************************************************
10083  _spoolss_CreatePrinterIC
10084 ****************************************************************/
10085
10086 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10087                                 struct spoolss_CreatePrinterIC *r)
10088 {
10089         p->rng_fault_state = true;
10090         return WERR_NOT_SUPPORTED;
10091 }
10092
10093 /****************************************************************
10094  _spoolss_PlayGDIScriptOnPrinterIC
10095 ****************************************************************/
10096
10097 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10098                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10099 {
10100         p->rng_fault_state = true;
10101         return WERR_NOT_SUPPORTED;
10102 }
10103
10104 /****************************************************************
10105  _spoolss_DeletePrinterIC
10106 ****************************************************************/
10107
10108 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10109                                 struct spoolss_DeletePrinterIC *r)
10110 {
10111         p->rng_fault_state = true;
10112         return WERR_NOT_SUPPORTED;
10113 }
10114
10115 /****************************************************************
10116  _spoolss_AddPrinterConnection
10117 ****************************************************************/
10118
10119 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10120                                      struct spoolss_AddPrinterConnection *r)
10121 {
10122         p->rng_fault_state = true;
10123         return WERR_NOT_SUPPORTED;
10124 }
10125
10126 /****************************************************************
10127  _spoolss_DeletePrinterConnection
10128 ****************************************************************/
10129
10130 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10131                                         struct spoolss_DeletePrinterConnection *r)
10132 {
10133         p->rng_fault_state = true;
10134         return WERR_NOT_SUPPORTED;
10135 }
10136
10137 /****************************************************************
10138  _spoolss_PrinterMessageBox
10139 ****************************************************************/
10140
10141 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10142                                   struct spoolss_PrinterMessageBox *r)
10143 {
10144         p->rng_fault_state = true;
10145         return WERR_NOT_SUPPORTED;
10146 }
10147
10148 /****************************************************************
10149  _spoolss_AddMonitor
10150 ****************************************************************/
10151
10152 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10153                            struct spoolss_AddMonitor *r)
10154 {
10155         p->rng_fault_state = true;
10156         return WERR_NOT_SUPPORTED;
10157 }
10158
10159 /****************************************************************
10160  _spoolss_DeleteMonitor
10161 ****************************************************************/
10162
10163 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10164                               struct spoolss_DeleteMonitor *r)
10165 {
10166         p->rng_fault_state = true;
10167         return WERR_NOT_SUPPORTED;
10168 }
10169
10170 /****************************************************************
10171  _spoolss_DeletePrintProcessor
10172 ****************************************************************/
10173
10174 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10175                                      struct spoolss_DeletePrintProcessor *r)
10176 {
10177         p->rng_fault_state = true;
10178         return WERR_NOT_SUPPORTED;
10179 }
10180
10181 /****************************************************************
10182  _spoolss_AddPrintProvidor
10183 ****************************************************************/
10184
10185 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10186                                  struct spoolss_AddPrintProvidor *r)
10187 {
10188         p->rng_fault_state = true;
10189         return WERR_NOT_SUPPORTED;
10190 }
10191
10192 /****************************************************************
10193  _spoolss_DeletePrintProvidor
10194 ****************************************************************/
10195
10196 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10197                                     struct spoolss_DeletePrintProvidor *r)
10198 {
10199         p->rng_fault_state = true;
10200         return WERR_NOT_SUPPORTED;
10201 }
10202
10203 /****************************************************************
10204  _spoolss_FindFirstPrinterChangeNotification
10205 ****************************************************************/
10206
10207 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10208                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10209 {
10210         p->rng_fault_state = true;
10211         return WERR_NOT_SUPPORTED;
10212 }
10213
10214 /****************************************************************
10215  _spoolss_FindNextPrinterChangeNotification
10216 ****************************************************************/
10217
10218 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10219                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10220 {
10221         p->rng_fault_state = true;
10222         return WERR_NOT_SUPPORTED;
10223 }
10224
10225 /****************************************************************
10226  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10227 ****************************************************************/
10228
10229 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10230                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10231 {
10232         p->rng_fault_state = true;
10233         return WERR_NOT_SUPPORTED;
10234 }
10235
10236 /****************************************************************
10237  _spoolss_ReplyOpenPrinter
10238 ****************************************************************/
10239
10240 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10241                                  struct spoolss_ReplyOpenPrinter *r)
10242 {
10243         p->rng_fault_state = true;
10244         return WERR_NOT_SUPPORTED;
10245 }
10246
10247 /****************************************************************
10248  _spoolss_RouterReplyPrinter
10249 ****************************************************************/
10250
10251 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10252                                    struct spoolss_RouterReplyPrinter *r)
10253 {
10254         p->rng_fault_state = true;
10255         return WERR_NOT_SUPPORTED;
10256 }
10257
10258 /****************************************************************
10259  _spoolss_ReplyClosePrinter
10260 ****************************************************************/
10261
10262 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10263                                   struct spoolss_ReplyClosePrinter *r)
10264 {
10265         p->rng_fault_state = true;
10266         return WERR_NOT_SUPPORTED;
10267 }
10268
10269 /****************************************************************
10270  _spoolss_AddPortEx
10271 ****************************************************************/
10272
10273 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10274                           struct spoolss_AddPortEx *r)
10275 {
10276         p->rng_fault_state = true;
10277         return WERR_NOT_SUPPORTED;
10278 }
10279
10280 /****************************************************************
10281  _spoolss_RouterFindFirstPrinterChangeNotification
10282 ****************************************************************/
10283
10284 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10285                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10286 {
10287         p->rng_fault_state = true;
10288         return WERR_NOT_SUPPORTED;
10289 }
10290
10291 /****************************************************************
10292  _spoolss_SpoolerInit
10293 ****************************************************************/
10294
10295 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10296                             struct spoolss_SpoolerInit *r)
10297 {
10298         p->rng_fault_state = true;
10299         return WERR_NOT_SUPPORTED;
10300 }
10301
10302 /****************************************************************
10303  _spoolss_ResetPrinterEx
10304 ****************************************************************/
10305
10306 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10307                                struct spoolss_ResetPrinterEx *r)
10308 {
10309         p->rng_fault_state = true;
10310         return WERR_NOT_SUPPORTED;
10311 }
10312
10313 /****************************************************************
10314  _spoolss_RouterReplyPrinterEx
10315 ****************************************************************/
10316
10317 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10318                                      struct spoolss_RouterReplyPrinterEx *r)
10319 {
10320         p->rng_fault_state = true;
10321         return WERR_NOT_SUPPORTED;
10322 }
10323
10324 /****************************************************************
10325  _spoolss_44
10326 ****************************************************************/
10327
10328 WERROR _spoolss_44(struct pipes_struct *p,
10329                    struct spoolss_44 *r)
10330 {
10331         p->rng_fault_state = true;
10332         return WERR_NOT_SUPPORTED;
10333 }
10334
10335 /****************************************************************
10336  _spoolss_SetPort
10337 ****************************************************************/
10338
10339 WERROR _spoolss_SetPort(struct pipes_struct *p,
10340                         struct spoolss_SetPort *r)
10341 {
10342         p->rng_fault_state = true;
10343         return WERR_NOT_SUPPORTED;
10344 }
10345
10346 /****************************************************************
10347  _spoolss_4a
10348 ****************************************************************/
10349
10350 WERROR _spoolss_4a(struct pipes_struct *p,
10351                    struct spoolss_4a *r)
10352 {
10353         p->rng_fault_state = true;
10354         return WERR_NOT_SUPPORTED;
10355 }
10356
10357 /****************************************************************
10358  _spoolss_4b
10359 ****************************************************************/
10360
10361 WERROR _spoolss_4b(struct pipes_struct *p,
10362                    struct spoolss_4b *r)
10363 {
10364         p->rng_fault_state = true;
10365         return WERR_NOT_SUPPORTED;
10366 }
10367
10368 /****************************************************************
10369  _spoolss_4c
10370 ****************************************************************/
10371
10372 WERROR _spoolss_4c(struct pipes_struct *p,
10373                    struct spoolss_4c *r)
10374 {
10375         p->rng_fault_state = true;
10376         return WERR_NOT_SUPPORTED;
10377 }
10378
10379 /****************************************************************
10380  _spoolss_53
10381 ****************************************************************/
10382
10383 WERROR _spoolss_53(struct pipes_struct *p,
10384                    struct spoolss_53 *r)
10385 {
10386         p->rng_fault_state = true;
10387         return WERR_NOT_SUPPORTED;
10388 }
10389
10390 /****************************************************************
10391  _spoolss_55
10392 ****************************************************************/
10393
10394 WERROR _spoolss_55(struct pipes_struct *p,
10395                    struct spoolss_55 *r)
10396 {
10397         p->rng_fault_state = true;
10398         return WERR_NOT_SUPPORTED;
10399 }
10400
10401 /****************************************************************
10402  _spoolss_56
10403 ****************************************************************/
10404
10405 WERROR _spoolss_56(struct pipes_struct *p,
10406                    struct spoolss_56 *r)
10407 {
10408         p->rng_fault_state = true;
10409         return WERR_NOT_SUPPORTED;
10410 }
10411
10412 /****************************************************************
10413  _spoolss_57
10414 ****************************************************************/
10415
10416 WERROR _spoolss_57(struct pipes_struct *p,
10417                    struct spoolss_57 *r)
10418 {
10419         p->rng_fault_state = true;
10420         return WERR_NOT_SUPPORTED;
10421 }
10422
10423 /****************************************************************
10424  _spoolss_5a
10425 ****************************************************************/
10426
10427 WERROR _spoolss_5a(struct pipes_struct *p,
10428                    struct spoolss_5a *r)
10429 {
10430         p->rng_fault_state = true;
10431         return WERR_NOT_SUPPORTED;
10432 }
10433
10434 /****************************************************************
10435  _spoolss_5b
10436 ****************************************************************/
10437
10438 WERROR _spoolss_5b(struct pipes_struct *p,
10439                    struct spoolss_5b *r)
10440 {
10441         p->rng_fault_state = true;
10442         return WERR_NOT_SUPPORTED;
10443 }
10444
10445 /****************************************************************
10446  _spoolss_5c
10447 ****************************************************************/
10448
10449 WERROR _spoolss_5c(struct pipes_struct *p,
10450                    struct spoolss_5c *r)
10451 {
10452         p->rng_fault_state = true;
10453         return WERR_NOT_SUPPORTED;
10454 }
10455
10456 /****************************************************************
10457  _spoolss_5d
10458 ****************************************************************/
10459
10460 WERROR _spoolss_5d(struct pipes_struct *p,
10461                    struct spoolss_5d *r)
10462 {
10463         p->rng_fault_state = true;
10464         return WERR_NOT_SUPPORTED;
10465 }
10466
10467 /****************************************************************
10468  _spoolss_5e
10469 ****************************************************************/
10470
10471 WERROR _spoolss_5e(struct pipes_struct *p,
10472                    struct spoolss_5e *r)
10473 {
10474         p->rng_fault_state = true;
10475         return WERR_NOT_SUPPORTED;
10476 }
10477
10478 /****************************************************************
10479  _spoolss_5f
10480 ****************************************************************/
10481
10482 WERROR _spoolss_5f(struct pipes_struct *p,
10483                    struct spoolss_5f *r)
10484 {
10485         p->rng_fault_state = true;
10486         return WERR_NOT_SUPPORTED;
10487 }
10488
10489 /****************************************************************
10490  _spoolss_60
10491 ****************************************************************/
10492
10493 WERROR _spoolss_60(struct pipes_struct *p,
10494                    struct spoolss_60 *r)
10495 {
10496         p->rng_fault_state = true;
10497         return WERR_NOT_SUPPORTED;
10498 }
10499
10500 /****************************************************************
10501  _spoolss_61
10502 ****************************************************************/
10503
10504 WERROR _spoolss_61(struct pipes_struct *p,
10505                    struct spoolss_61 *r)
10506 {
10507         p->rng_fault_state = true;
10508         return WERR_NOT_SUPPORTED;
10509 }
10510
10511 /****************************************************************
10512  _spoolss_62
10513 ****************************************************************/
10514
10515 WERROR _spoolss_62(struct pipes_struct *p,
10516                    struct spoolss_62 *r)
10517 {
10518         p->rng_fault_state = true;
10519         return WERR_NOT_SUPPORTED;
10520 }
10521
10522 /****************************************************************
10523  _spoolss_63
10524 ****************************************************************/
10525
10526 WERROR _spoolss_63(struct pipes_struct *p,
10527                    struct spoolss_63 *r)
10528 {
10529         p->rng_fault_state = true;
10530         return WERR_NOT_SUPPORTED;
10531 }
10532
10533 /****************************************************************
10534  _spoolss_64
10535 ****************************************************************/
10536
10537 WERROR _spoolss_64(struct pipes_struct *p,
10538                    struct spoolss_64 *r)
10539 {
10540         p->rng_fault_state = true;
10541         return WERR_NOT_SUPPORTED;
10542 }
10543
10544 /****************************************************************
10545  _spoolss_65
10546 ****************************************************************/
10547
10548 WERROR _spoolss_65(struct pipes_struct *p,
10549                    struct spoolss_65 *r)
10550 {
10551         p->rng_fault_state = true;
10552         return WERR_NOT_SUPPORTED;
10553 }
10554
10555 /****************************************************************
10556  _spoolss_GetCorePrinterDrivers
10557 ****************************************************************/
10558
10559 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10560                                       struct spoolss_GetCorePrinterDrivers *r)
10561 {
10562         p->rng_fault_state = true;
10563         return WERR_NOT_SUPPORTED;
10564 }
10565
10566 /****************************************************************
10567  _spoolss_67
10568 ****************************************************************/
10569
10570 WERROR _spoolss_67(struct pipes_struct *p,
10571                    struct spoolss_67 *r)
10572 {
10573         p->rng_fault_state = true;
10574         return WERR_NOT_SUPPORTED;
10575 }
10576
10577 /****************************************************************
10578  _spoolss_GetPrinterDriverPackagePath
10579 ****************************************************************/
10580
10581 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10582                                             struct spoolss_GetPrinterDriverPackagePath *r)
10583 {
10584         p->rng_fault_state = true;
10585         return WERR_NOT_SUPPORTED;
10586 }
10587
10588 /****************************************************************
10589  _spoolss_69
10590 ****************************************************************/
10591
10592 WERROR _spoolss_69(struct pipes_struct *p,
10593                    struct spoolss_69 *r)
10594 {
10595         p->rng_fault_state = true;
10596         return WERR_NOT_SUPPORTED;
10597 }
10598
10599 /****************************************************************
10600  _spoolss_6a
10601 ****************************************************************/
10602
10603 WERROR _spoolss_6a(struct pipes_struct *p,
10604                    struct spoolss_6a *r)
10605 {
10606         p->rng_fault_state = true;
10607         return WERR_NOT_SUPPORTED;
10608 }
10609
10610 /****************************************************************
10611  _spoolss_6b
10612 ****************************************************************/
10613
10614 WERROR _spoolss_6b(struct pipes_struct *p,
10615                    struct spoolss_6b *r)
10616 {
10617         p->rng_fault_state = true;
10618         return WERR_NOT_SUPPORTED;
10619 }
10620
10621 /****************************************************************
10622  _spoolss_6c
10623 ****************************************************************/
10624
10625 WERROR _spoolss_6c(struct pipes_struct *p,
10626                    struct spoolss_6c *r)
10627 {
10628         p->rng_fault_state = true;
10629         return WERR_NOT_SUPPORTED;
10630 }
10631
10632 /****************************************************************
10633  _spoolss_6d
10634 ****************************************************************/
10635
10636 WERROR _spoolss_6d(struct pipes_struct *p,
10637                    struct spoolss_6d *r)
10638 {
10639         p->rng_fault_state = true;
10640         return WERR_NOT_SUPPORTED;
10641 }