s3-smbd provide struct smbd_server_connection * to conn_snum_used
[ddiss/samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "registry/reg_objects.h"
42 #include "include/printing.h"
43 #include "secrets.h"
44 #include "../librpc/gen_ndr/netlogon.h"
45 #include "rpc_misc.h"
46 #include "printing/notify.h"
47 #include "serverid.h"
48 #include "../libcli/registry/util_reg.h"
49 #include "smbd/smbd.h"
50 #include "smbd/globals.h"
51 #include "auth.h"
52 #include "messages.h"
53 #include "rpc_server/spoolss/srv_spoolss_nt.h"
54 #include "util_tdb.h"
55 #include "libsmb/libsmb.h"
56 #include "printing/printer_list.h"
57
58 /* macros stolen from s4 spoolss server */
59 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
60         ((info)?ndr_size_##fn(info, level, 0):0)
61
62 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
63         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
64
65 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
66         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
67
68 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
69
70 #undef DBGC_CLASS
71 #define DBGC_CLASS DBGC_RPC_SRV
72
73 #ifndef MAX_OPEN_PRINTER_EXS
74 #define MAX_OPEN_PRINTER_EXS 50
75 #endif
76
77 struct notify_back_channel;
78
79 /* structure to store the printer handles */
80 /* and a reference to what it's pointing to */
81 /* and the notify info asked about */
82 /* that's the central struct */
83 struct printer_handle {
84         struct printer_handle *prev, *next;
85         bool document_started;
86         bool page_started;
87         uint32 jobid; /* jobid in printing backend */
88         int printer_type;
89         const char *servername;
90         fstring sharename;
91         uint32 type;
92         uint32 access_granted;
93         struct {
94                 uint32 flags;
95                 uint32 options;
96                 fstring localmachine;
97                 uint32 printerlocal;
98                 struct spoolss_NotifyOption *option;
99                 struct policy_handle cli_hnd;
100                 struct notify_back_channel *cli_chan;
101                 uint32 change;
102                 /* are we in a FindNextPrinterChangeNotify() call? */
103                 bool fnpcn;
104                 struct messaging_context *msg_ctx;
105         } notify;
106         struct {
107                 fstring machine;
108                 fstring user;
109         } client;
110
111         /* devmode sent in the OpenPrinter() call */
112         struct spoolss_DeviceMode *devmode;
113
114         /* TODO cache the printer info2 structure */
115         struct spoolss_PrinterInfo2 *info2;
116
117 };
118
119 static struct printer_handle *printers_list;
120
121 struct printer_session_counter {
122         struct printer_session_counter *next;
123         struct printer_session_counter *prev;
124
125         int snum;
126         uint32_t counter;
127 };
128
129 static struct printer_session_counter *counter_list;
130
131 struct notify_back_channel {
132         struct notify_back_channel *prev, *next;
133
134         /* associated client */
135         struct sockaddr_storage client_address;
136
137         /* print notify back-channel pipe handle*/
138         struct rpc_pipe_client *cli_pipe;
139         struct dcerpc_binding_handle *binding_handle;
140         uint32_t active_connections;
141 };
142
143 static struct notify_back_channel *back_channels;
144
145 /* Map generic permissions to printer object specific permissions */
146
147 const struct standard_mapping printer_std_mapping = {
148         PRINTER_READ,
149         PRINTER_WRITE,
150         PRINTER_EXECUTE,
151         PRINTER_ALL_ACCESS
152 };
153
154 /* Map generic permissions to print server object specific permissions */
155
156 const struct standard_mapping printserver_std_mapping = {
157         SERVER_READ,
158         SERVER_WRITE,
159         SERVER_EXECUTE,
160         SERVER_ALL_ACCESS
161 };
162
163 /* API table for Xcv Monitor functions */
164
165 struct xcv_api_table {
166         const char *name;
167         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
168 };
169
170 static void prune_printername_cache(void);
171
172 /********************************************************************
173  * Canonicalize servername.
174  ********************************************************************/
175
176 static const char *canon_servername(const char *servername)
177 {
178         const char *pservername = servername;
179         while (*pservername == '\\') {
180                 pservername++;
181         }
182         return pservername;
183 }
184
185 /* translate between internal status numbers and NT status numbers */
186 static int nt_printj_status(int v)
187 {
188         switch (v) {
189         case LPQ_QUEUED:
190                 return 0;
191         case LPQ_PAUSED:
192                 return JOB_STATUS_PAUSED;
193         case LPQ_SPOOLING:
194                 return JOB_STATUS_SPOOLING;
195         case LPQ_PRINTING:
196                 return JOB_STATUS_PRINTING;
197         case LPQ_ERROR:
198                 return JOB_STATUS_ERROR;
199         case LPQ_DELETING:
200                 return JOB_STATUS_DELETING;
201         case LPQ_OFFLINE:
202                 return JOB_STATUS_OFFLINE;
203         case LPQ_PAPEROUT:
204                 return JOB_STATUS_PAPEROUT;
205         case LPQ_PRINTED:
206                 return JOB_STATUS_PRINTED;
207         case LPQ_DELETED:
208                 return JOB_STATUS_DELETED;
209         case LPQ_BLOCKED:
210                 return JOB_STATUS_BLOCKED_DEVQ;
211         case LPQ_USER_INTERVENTION:
212                 return JOB_STATUS_USER_INTERVENTION;
213         }
214         return 0;
215 }
216
217 static int nt_printq_status(int v)
218 {
219         switch (v) {
220         case LPQ_PAUSED:
221                 return PRINTER_STATUS_PAUSED;
222         case LPQ_QUEUED:
223         case LPQ_SPOOLING:
224         case LPQ_PRINTING:
225                 return 0;
226         }
227         return 0;
228 }
229
230 /***************************************************************************
231  Disconnect from the client
232 ****************************************************************************/
233
234 static void srv_spoolss_replycloseprinter(int snum,
235                                           struct printer_handle *prn_hnd)
236 {
237         WERROR result;
238         NTSTATUS status;
239
240         /*
241          * Tell the specific printing tdb we no longer want messages for this printer
242          * by deregistering our PID.
243          */
244
245         if (!print_notify_deregister_pid(snum)) {
246                 DEBUG(0, ("Failed to register our pid for printer %s\n",
247                           lp_const_servicename(snum)));
248         }
249
250         /* weird if the test succeeds !!! */
251         if (prn_hnd->notify.cli_chan == NULL ||
252             prn_hnd->notify.cli_chan->active_connections == 0) {
253                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
254                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
255                 TALLOC_FREE(prn_hnd->notify.cli_chan);
256                 return;
257         }
258
259         status = dcerpc_spoolss_ReplyClosePrinter(
260                                         prn_hnd->notify.cli_chan->binding_handle,
261                                         talloc_tos(),
262                                         &prn_hnd->notify.cli_hnd,
263                                         &result);
264         if (!NT_STATUS_IS_OK(status)) {
265                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
266                           nt_errstr(status)));
267                 result = ntstatus_to_werror(status);
268         } else if (!W_ERROR_IS_OK(result)) {
269                 DEBUG(0, ("reply_close_printer failed [%s].\n",
270                           win_errstr(result)));
271         }
272
273         /* if it's the last connection, deconnect the IPC$ share */
274         if (prn_hnd->notify.cli_chan->active_connections == 1) {
275
276                 prn_hnd->notify.cli_chan->binding_handle = NULL;
277                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
278                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
279                 TALLOC_FREE(prn_hnd->notify.cli_chan);
280
281                 if (prn_hnd->notify.msg_ctx != NULL) {
282                         messaging_deregister(prn_hnd->notify.msg_ctx,
283                                              MSG_PRINTER_NOTIFY2, NULL);
284
285                         /*
286                          * Tell the serverid.tdb we're no longer
287                          * interested in printer notify messages.
288                          */
289
290                         serverid_register_msg_flags(
291                                 messaging_server_id(prn_hnd->notify.msg_ctx),
292                                 false, FLAG_MSG_PRINT_NOTIFY);
293                 }
294         }
295
296         if (prn_hnd->notify.cli_chan) {
297                 prn_hnd->notify.cli_chan->active_connections--;
298         }
299 }
300
301 /****************************************************************************
302  Functions to free a printer entry datastruct.
303 ****************************************************************************/
304
305 static int printer_entry_destructor(struct printer_handle *Printer)
306 {
307         if (Printer->notify.cli_chan != NULL &&
308             Printer->notify.cli_chan->active_connections > 0) {
309                 int snum = -1;
310
311                 switch(Printer->printer_type) {
312                 case SPLHND_SERVER:
313                         srv_spoolss_replycloseprinter(snum, Printer);
314                         break;
315
316                 case SPLHND_PRINTER:
317                         snum = print_queue_snum(Printer->sharename);
318                         if (snum != -1) {
319                                 srv_spoolss_replycloseprinter(snum, Printer);
320                         }
321                         break;
322                 default:
323                         break;
324                 }
325         }
326
327         Printer->notify.flags=0;
328         Printer->notify.options=0;
329         Printer->notify.localmachine[0]='\0';
330         Printer->notify.printerlocal=0;
331         TALLOC_FREE(Printer->notify.option);
332         TALLOC_FREE(Printer->devmode);
333
334         /* Remove from the internal list. */
335         DLIST_REMOVE(printers_list, Printer);
336         return 0;
337 }
338
339 /****************************************************************************
340   find printer index by handle
341 ****************************************************************************/
342
343 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
344                                                         struct policy_handle *hnd)
345 {
346         struct printer_handle *find_printer = NULL;
347
348         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
349                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
350                 return NULL;
351         }
352
353         return find_printer;
354 }
355
356 /****************************************************************************
357  Close printer index by handle.
358 ****************************************************************************/
359
360 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
361 {
362         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
363
364         if (!Printer) {
365                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
366                         OUR_HANDLE(hnd)));
367                 return false;
368         }
369
370         close_policy_hnd(p, hnd);
371
372         return true;
373 }
374
375 /****************************************************************************
376  Delete a printer given a handle.
377 ****************************************************************************/
378
379 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
380                                   const char *sharename,
381                                   struct messaging_context *msg_ctx)
382 {
383         char *cmd = lp_deleteprinter_cmd();
384         char *command = NULL;
385         int ret;
386         bool is_print_op = false;
387
388         /* can't fail if we don't try */
389
390         if ( !*cmd )
391                 return WERR_OK;
392
393         command = talloc_asprintf(ctx,
394                         "%s \"%s\"",
395                         cmd, sharename);
396         if (!command) {
397                 return WERR_NOMEM;
398         }
399         if ( token )
400                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
401
402         DEBUG(10,("Running [%s]\n", command));
403
404         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
405
406         if ( is_print_op )
407                 become_root();
408
409         if ( (ret = smbrun(command, NULL)) == 0 ) {
410                 /* Tell everyone we updated smb.conf. */
411                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
412         }
413
414         if ( is_print_op )
415                 unbecome_root();
416
417         /********** END SePrintOperatorPrivlege BLOCK **********/
418
419         DEBUGADD(10,("returned [%d]\n", ret));
420
421         TALLOC_FREE(command);
422
423         if (ret != 0)
424                 return WERR_BADFID; /* What to return here? */
425
426         /* go ahead and re-read the services immediately */
427         become_root();
428         reload_services(msg_ctx, -1, false);
429         unbecome_root();
430
431         if ( lp_servicenumber( sharename ) >= 0 )
432                 return WERR_ACCESS_DENIED;
433
434         return WERR_OK;
435 }
436
437 /****************************************************************************
438  Delete a printer given a handle.
439 ****************************************************************************/
440
441 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
442 {
443         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
444         WERROR result;
445
446         if (!Printer) {
447                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
448                         OUR_HANDLE(hnd)));
449                 return WERR_BADFID;
450         }
451
452         /*
453          * It turns out that Windows allows delete printer on a handle
454          * opened by an admin user, then used on a pipe handle created
455          * by an anonymous user..... but they're working on security.... riiight !
456          * JRA.
457          */
458
459         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
460                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
461                 return WERR_ACCESS_DENIED;
462         }
463
464         /* this does not need a become root since the access check has been
465            done on the handle already */
466
467         result = winreg_delete_printer_key(p->mem_ctx,
468                                            get_session_info_system(),
469                                            p->msg_ctx,
470                                            Printer->sharename,
471                                            "");
472         if (!W_ERROR_IS_OK(result)) {
473                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
474                 return WERR_BADFID;
475         }
476
477         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
478                                      Printer->sharename, p->msg_ctx);
479         if (!W_ERROR_IS_OK(result)) {
480                 return result;
481         }
482         prune_printername_cache();
483         return WERR_OK;
484 }
485
486 /****************************************************************************
487  Return the snum of a printer corresponding to an handle.
488 ****************************************************************************/
489
490 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
491                              int *number, struct share_params **params)
492 {
493         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
494
495         if (!Printer) {
496                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
497                         OUR_HANDLE(hnd)));
498                 return false;
499         }
500
501         switch (Printer->printer_type) {
502                 case SPLHND_PRINTER:
503                         DEBUG(4,("short name:%s\n", Printer->sharename));
504                         *number = print_queue_snum(Printer->sharename);
505                         return (*number != -1);
506                 case SPLHND_SERVER:
507                         return false;
508                 default:
509                         return false;
510         }
511 }
512
513 /****************************************************************************
514  Set printer handle type.
515  Check if it's \\server or \\server\printer
516 ****************************************************************************/
517
518 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
519 {
520         DEBUG(3,("Setting printer type=%s\n", handlename));
521
522         /* it's a print server */
523         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
524                 DEBUGADD(4,("Printer is a print server\n"));
525                 Printer->printer_type = SPLHND_SERVER;
526         }
527         /* it's a printer (set_printer_hnd_name() will handle port monitors */
528         else {
529                 DEBUGADD(4,("Printer is a printer\n"));
530                 Printer->printer_type = SPLHND_PRINTER;
531         }
532
533         return true;
534 }
535
536 static void prune_printername_cache_fn(const char *key, const char *value,
537                                        time_t timeout, void *private_data)
538 {
539         gencache_del(key);
540 }
541
542 static void prune_printername_cache(void)
543 {
544         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
545 }
546
547 /****************************************************************************
548  Set printer handle name..  Accept names like \\server, \\server\printer,
549  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
550  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
551  XcvDataPort() interface.
552 ****************************************************************************/
553
554 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
555                                    const struct auth_serversupplied_info *session_info,
556                                    struct messaging_context *msg_ctx,
557                                    struct printer_handle *Printer,
558                                    const char *handlename)
559 {
560         int snum;
561         int n_services=lp_numservices();
562         char *aprinter;
563         const char *printername;
564         const char *servername = NULL;
565         fstring sname;
566         bool found = false;
567         struct spoolss_PrinterInfo2 *info2 = NULL;
568         WERROR result;
569         char *p;
570
571         /*
572          * Hopefully nobody names his printers like this. Maybe \ or ,
573          * are illegal in printer names even?
574          */
575         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
576         char *cache_key;
577         char *tmp;
578
579         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
580                 (unsigned long)strlen(handlename)));
581
582         aprinter = discard_const_p(char, handlename);
583         if ( *handlename == '\\' ) {
584                 servername = canon_servername(handlename);
585                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
586                         *aprinter = '\0';
587                         aprinter++;
588                 }
589                 if (!is_myname_or_ipaddr(servername)) {
590                         return WERR_INVALID_PRINTER_NAME;
591                 }
592                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
593                 if (Printer->servername == NULL) {
594                         return WERR_NOMEM;
595                 }
596         }
597
598         if (Printer->printer_type == SPLHND_SERVER) {
599                 return WERR_OK;
600         }
601
602         if (Printer->printer_type != SPLHND_PRINTER) {
603                 return WERR_INVALID_HANDLE;
604         }
605
606         DEBUGADD(5, ("searching for [%s]\n", aprinter));
607
608         p = strchr(aprinter, ',');
609         if (p != NULL) {
610                 char *p2 = p;
611                 p++;
612                 if (*p == ' ') {
613                         p++;
614                 }
615                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
616                         *p2 = '\0';
617                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
618                         *p2 = '\0';
619                 }
620         }
621
622         if (p) {
623                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
624         }
625
626         /* check for the Port Monitor Interface */
627         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
628                 Printer->printer_type = SPLHND_PORTMON_TCP;
629                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
630                 found = true;
631         }
632         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
633                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
634                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
635                 found = true;
636         }
637
638         /*
639          * With hundreds of printers, the "for" loop iterating all
640          * shares can be quite expensive, as it is done on every
641          * OpenPrinter. The loop maps "aprinter" to "sname", the
642          * result of which we cache in gencache.
643          */
644
645         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
646                                     aprinter);
647         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
648
649                 found = (strcmp(tmp, printer_not_found) != 0);
650                 if (!found) {
651                         DEBUG(4, ("Printer %s not found\n", aprinter));
652                         SAFE_FREE(tmp);
653                         return WERR_INVALID_PRINTER_NAME;
654                 }
655                 fstrcpy(sname, tmp);
656                 SAFE_FREE(tmp);
657         }
658
659         /* Search all sharenames first as this is easier than pulling
660            the printer_info_2 off of disk. Don't use find_service() since
661            that calls out to map_username() */
662
663         /* do another loop to look for printernames */
664         for (snum = 0; !found && snum < n_services; snum++) {
665                 const char *printer = lp_const_servicename(snum);
666
667                 /* no point going on if this is not a printer */
668                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
669                         continue;
670                 }
671
672                 /* ignore [printers] share */
673                 if (strequal(printer, "printers")) {
674                         continue;
675                 }
676
677                 fstrcpy(sname, printer);
678                 if (strequal(aprinter, printer)) {
679                         found = true;
680                         break;
681                 }
682
683                 /* no point looking up the printer object if
684                    we aren't allowing printername != sharename */
685                 if (lp_force_printername(snum)) {
686                         continue;
687                 }
688
689                 result = winreg_get_printer(mem_ctx,
690                                             session_info,
691                                             msg_ctx,
692                                             sname,
693                                             &info2);
694                 if ( !W_ERROR_IS_OK(result) ) {
695                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
696                                  sname, win_errstr(result)));
697                         continue;
698                 }
699
700                 printername = strrchr(info2->printername, '\\');
701                 if (printername == NULL) {
702                         printername = info2->printername;
703                 } else {
704                         printername++;
705                 }
706
707                 if (strequal(printername, aprinter)) {
708                         found = true;
709                         break;
710                 }
711
712                 DEBUGADD(10, ("printername: %s\n", printername));
713
714                 TALLOC_FREE(info2);
715         }
716
717         if ( !found ) {
718                 if (cache_key != NULL) {
719                         gencache_set(cache_key, printer_not_found,
720                                      time(NULL)+300);
721                         TALLOC_FREE(cache_key);
722                 }
723                 DEBUGADD(4,("Printer not found\n"));
724                 return WERR_INVALID_PRINTER_NAME;
725         }
726
727         if (cache_key != NULL) {
728                 gencache_set(cache_key, sname, time(NULL)+300);
729                 TALLOC_FREE(cache_key);
730         }
731
732         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
733
734         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
735
736         return WERR_OK;
737 }
738
739 /****************************************************************************
740  Find first available printer slot. creates a printer handle for you.
741  ****************************************************************************/
742
743 static WERROR open_printer_hnd(struct pipes_struct *p,
744                                struct policy_handle *hnd,
745                                const char *name,
746                                uint32_t access_granted)
747 {
748         struct printer_handle *new_printer;
749         WERROR result;
750
751         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
752
753         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
754         if (new_printer == NULL) {
755                 return WERR_NOMEM;
756         }
757         talloc_set_destructor(new_printer, printer_entry_destructor);
758
759         /* This also steals the printer_handle on the policy_handle */
760         if (!create_policy_hnd(p, hnd, new_printer)) {
761                 TALLOC_FREE(new_printer);
762                 return WERR_INVALID_HANDLE;
763         }
764
765         /* Add to the internal list. */
766         DLIST_ADD(printers_list, new_printer);
767
768         new_printer->notify.option=NULL;
769
770         if (!set_printer_hnd_printertype(new_printer, name)) {
771                 close_printer_handle(p, hnd);
772                 return WERR_INVALID_HANDLE;
773         }
774
775         result = set_printer_hnd_name(p->mem_ctx,
776                                       get_session_info_system(),
777                                       p->msg_ctx,
778                                       new_printer, name);
779         if (!W_ERROR_IS_OK(result)) {
780                 close_printer_handle(p, hnd);
781                 return result;
782         }
783
784         new_printer->access_granted = access_granted;
785
786         DEBUG(5, ("%d printer handles active\n",
787                   (int)num_pipe_handles(p)));
788
789         return WERR_OK;
790 }
791
792 /***************************************************************************
793  check to see if the client motify handle is monitoring the notification
794  given by (notify_type, notify_field).
795  **************************************************************************/
796
797 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
798                                       uint16_t notify_field)
799 {
800         return true;
801 }
802
803 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
804                                 uint16_t notify_field)
805 {
806         struct spoolss_NotifyOption *option = p->notify.option;
807         uint32_t i, j;
808
809         /*
810          * Flags should always be zero when the change notify
811          * is registered by the client's spooler.  A user Win32 app
812          * might use the flags though instead of the NOTIFY_OPTION_INFO
813          * --jerry
814          */
815
816         if (!option) {
817                 return false;
818         }
819
820         if (p->notify.flags)
821                 return is_monitoring_event_flags(
822                         p->notify.flags, notify_type, notify_field);
823
824         for (i = 0; i < option->count; i++) {
825
826                 /* Check match for notify_type */
827
828                 if (option->types[i].type != notify_type)
829                         continue;
830
831                 /* Check match for field */
832
833                 for (j = 0; j < option->types[i].count; j++) {
834                         if (option->types[i].fields[j].field == notify_field) {
835                                 return true;
836                         }
837                 }
838         }
839
840         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
841                    p->servername, p->sharename, notify_type, notify_field));
842
843         return false;
844 }
845
846 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
847         _data->data.integer[0] = _integer; \
848         _data->data.integer[1] = 0;
849
850
851 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
852         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
853         if (!_data->data.string.string) {\
854                 _data->data.string.size = 0; \
855         } \
856         _data->data.string.size = strlen_m_term(_p) * 2;
857
858 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
859         _data->data.devmode.devmode = _devmode;
860
861 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
862         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
863         if (!_data->data.sd.sd) { \
864                 _data->data.sd.sd_size = 0; \
865         } \
866         _data->data.sd.sd_size = \
867                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
868
869 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
870                                    struct tm *t,
871                                    const char **pp,
872                                    uint32_t *plen)
873 {
874         struct spoolss_Time st;
875         uint32_t len = 16;
876         char *p;
877
878         if (!init_systemtime(&st, t)) {
879                 return;
880         }
881
882         p = talloc_array(mem_ctx, char, len);
883         if (!p) {
884                 return;
885         }
886
887         /*
888          * Systemtime must be linearized as a set of UINT16's.
889          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
890          */
891
892         SSVAL(p, 0, st.year);
893         SSVAL(p, 2, st.month);
894         SSVAL(p, 4, st.day_of_week);
895         SSVAL(p, 6, st.day);
896         SSVAL(p, 8, st.hour);
897         SSVAL(p, 10, st.minute);
898         SSVAL(p, 12, st.second);
899         SSVAL(p, 14, st.millisecond);
900
901         *pp = p;
902         *plen = len;
903 }
904
905 /* Convert a notification message to a struct spoolss_Notify */
906
907 static void notify_one_value(struct spoolss_notify_msg *msg,
908                              struct spoolss_Notify *data,
909                              TALLOC_CTX *mem_ctx)
910 {
911         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
912 }
913
914 static void notify_string(struct spoolss_notify_msg *msg,
915                           struct spoolss_Notify *data,
916                           TALLOC_CTX *mem_ctx)
917 {
918         /* The length of the message includes the trailing \0 */
919
920         data->data.string.size = msg->len * 2;
921         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
922         if (!data->data.string.string) {
923                 data->data.string.size = 0;
924                 return;
925         }
926 }
927
928 static void notify_system_time(struct spoolss_notify_msg *msg,
929                                struct spoolss_Notify *data,
930                                TALLOC_CTX *mem_ctx)
931 {
932         data->data.string.string = NULL;
933         data->data.string.size = 0;
934
935         if (msg->len != sizeof(time_t)) {
936                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
937                           msg->len));
938                 return;
939         }
940
941         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
942                                &data->data.string.string,
943                                &data->data.string.size);
944 }
945
946 struct notify2_message_table {
947         const char *name;
948         void (*fn)(struct spoolss_notify_msg *msg,
949                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
950 };
951
952 static struct notify2_message_table printer_notify_table[] = {
953         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
954         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
955         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
956         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
957         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
958         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
959         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
960         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
961         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
962         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
963         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
964         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
965         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
966         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
967         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
968         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
969         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
970         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
971         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
972 };
973
974 static struct notify2_message_table job_notify_table[] = {
975         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
976         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
977         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
978         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
979         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
980         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
981         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
982         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
983         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
984         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
985         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
986         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
987         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
988         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
989         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
990         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
991         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
992         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
993         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
994         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
995         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
996         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
997         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
998         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
999 };
1000
1001
1002 /***********************************************************************
1003  Allocate talloc context for container object
1004  **********************************************************************/
1005
1006 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1007 {
1008         if ( !ctr )
1009                 return;
1010
1011         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1012
1013         return;
1014 }
1015
1016 /***********************************************************************
1017  release all allocated memory and zero out structure
1018  **********************************************************************/
1019
1020 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1021 {
1022         if ( !ctr )
1023                 return;
1024
1025         if ( ctr->ctx )
1026                 talloc_destroy(ctr->ctx);
1027
1028         ZERO_STRUCTP(ctr);
1029
1030         return;
1031 }
1032
1033 /***********************************************************************
1034  **********************************************************************/
1035
1036 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1037 {
1038         if ( !ctr )
1039                 return NULL;
1040
1041         return ctr->ctx;
1042 }
1043
1044 /***********************************************************************
1045  **********************************************************************/
1046
1047 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1048 {
1049         if ( !ctr || !ctr->msg_groups )
1050                 return NULL;
1051
1052         if ( idx >= ctr->num_groups )
1053                 return NULL;
1054
1055         return &ctr->msg_groups[idx];
1056
1057 }
1058
1059 /***********************************************************************
1060  How many groups of change messages do we have ?
1061  **********************************************************************/
1062
1063 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1064 {
1065         if ( !ctr )
1066                 return 0;
1067
1068         return ctr->num_groups;
1069 }
1070
1071 /***********************************************************************
1072  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1073  **********************************************************************/
1074
1075 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1076 {
1077         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1078         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1079         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1080         int                             i, new_slot;
1081
1082         if ( !ctr || !msg )
1083                 return 0;
1084
1085         /* loop over all groups looking for a matching printer name */
1086
1087         for ( i=0; i<ctr->num_groups; i++ ) {
1088                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1089                         break;
1090         }
1091
1092         /* add a new group? */
1093
1094         if ( i == ctr->num_groups ) {
1095                 ctr->num_groups++;
1096
1097                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1098                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1099                         return 0;
1100                 }
1101                 ctr->msg_groups = groups;
1102
1103                 /* clear the new entry and set the printer name */
1104
1105                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1106                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1107         }
1108
1109         /* add the change messages; 'i' is the correct index now regardless */
1110
1111         msg_grp = &ctr->msg_groups[i];
1112
1113         msg_grp->num_msgs++;
1114
1115         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1116                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1117                 return 0;
1118         }
1119         msg_grp->msgs = msg_list;
1120
1121         new_slot = msg_grp->num_msgs-1;
1122         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1123
1124         /* need to allocate own copy of data */
1125
1126         if ( msg->len != 0 )
1127                 msg_grp->msgs[new_slot].notify.data = (char *)
1128                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1129
1130         return ctr->num_groups;
1131 }
1132
1133 static void construct_info_data(struct spoolss_Notify *info_data,
1134                                 enum spoolss_NotifyType type,
1135                                 uint16_t field, int id);
1136
1137 /***********************************************************************
1138  Send a change notication message on all handles which have a call
1139  back registered
1140  **********************************************************************/
1141
1142 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1143                                   struct printer_handle *prn_hnd,
1144                                   SPOOLSS_NOTIFY_MSG *messages,
1145                                   uint32_t num_msgs,
1146                                   struct spoolss_Notify **_notifies,
1147                                   int *_count)
1148 {
1149         struct spoolss_Notify *notifies;
1150         SPOOLSS_NOTIFY_MSG *msg;
1151         int count = 0;
1152         uint32_t id;
1153         int i;
1154
1155         notifies = talloc_zero_array(mem_ctx,
1156                                      struct spoolss_Notify, num_msgs);
1157         if (!notifies) {
1158                 return ENOMEM;
1159         }
1160
1161         for (i = 0; i < num_msgs; i++) {
1162
1163                 msg = &messages[i];
1164
1165                 /* Are we monitoring this event? */
1166
1167                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1168                         continue;
1169                 }
1170
1171                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1172                            "for printer [%s]\n",
1173                            msg->type, msg->field, prn_hnd->sharename));
1174
1175                 /*
1176                  * if the is a printer notification handle and not a job
1177                  * notification type, then set the id to 0.
1178                  * Otherwise just use what was specified in the message.
1179                  *
1180                  * When registering change notification on a print server
1181                  * handle we always need to send back the id (snum) matching
1182                  * the printer for which the change took place.
1183                  * For change notify registered on a printer handle,
1184                  * this does not matter and the id should be 0.
1185                  *
1186                  * --jerry
1187                  */
1188
1189                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1190                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1191                         id = 0;
1192                 } else {
1193                         id = msg->id;
1194                 }
1195
1196                 /* Convert unix jobid to smb jobid */
1197
1198                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1199                         id = sysjob_to_jobid(msg->id);
1200
1201                         if (id == -1) {
1202                                 DEBUG(3, ("no such unix jobid %d\n",
1203                                           msg->id));
1204                                 continue;
1205                         }
1206                 }
1207
1208                 construct_info_data(&notifies[count],
1209                                     msg->type, msg->field, id);
1210
1211                 switch(msg->type) {
1212                 case PRINTER_NOTIFY_TYPE:
1213                         if (printer_notify_table[msg->field].fn) {
1214                                 printer_notify_table[msg->field].fn(msg,
1215                                                 &notifies[count], mem_ctx);
1216                         }
1217                         break;
1218
1219                 case JOB_NOTIFY_TYPE:
1220                         if (job_notify_table[msg->field].fn) {
1221                                 job_notify_table[msg->field].fn(msg,
1222                                                 &notifies[count], mem_ctx);
1223                         }
1224                         break;
1225
1226                 default:
1227                         DEBUG(5, ("Unknown notification type %d\n",
1228                                   msg->type));
1229                         continue;
1230                 }
1231
1232                 count++;
1233         }
1234
1235         *_notifies = notifies;
1236         *_count = count;
1237
1238         return 0;
1239 }
1240
1241 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1242                                 struct printer_handle *prn_hnd,
1243                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1244 {
1245         struct spoolss_Notify *notifies;
1246         int count = 0;
1247         union spoolss_ReplyPrinterInfo info;
1248         struct spoolss_NotifyInfo info0;
1249         uint32_t reply_result;
1250         NTSTATUS status;
1251         WERROR werr;
1252         int ret;
1253
1254         /* Is there notification on this handle? */
1255         if (prn_hnd->notify.cli_chan == NULL ||
1256             prn_hnd->notify.cli_chan->active_connections == 0) {
1257                 return 0;
1258         }
1259
1260         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1261                    prn_hnd->servername, prn_hnd->sharename));
1262
1263         /* For this printer? Print servers always receive notifications. */
1264         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1265             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1266                 return 0;
1267         }
1268
1269         DEBUG(10,("Our printer\n"));
1270
1271         /* build the array of change notifications */
1272         ret = build_notify2_messages(mem_ctx, prn_hnd,
1273                                      msg_group->msgs,
1274                                      msg_group->num_msgs,
1275                                      &notifies, &count);
1276         if (ret) {
1277                 return ret;
1278         }
1279
1280         info0.version   = 0x2;
1281         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1282         info0.count     = count;
1283         info0.notifies  = notifies;
1284
1285         info.info0 = &info0;
1286
1287         status = dcerpc_spoolss_RouterReplyPrinterEx(
1288                                 prn_hnd->notify.cli_chan->binding_handle,
1289                                 mem_ctx,
1290                                 &prn_hnd->notify.cli_hnd,
1291                                 prn_hnd->notify.change, /* color */
1292                                 prn_hnd->notify.flags,
1293                                 &reply_result,
1294                                 0, /* reply_type, must be 0 */
1295                                 info, &werr);
1296         if (!NT_STATUS_IS_OK(status)) {
1297                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1298                           "failed: %s\n",
1299                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1300                           nt_errstr(status)));
1301                 werr = ntstatus_to_werror(status);
1302         } else if (!W_ERROR_IS_OK(werr)) {
1303                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1304                           "failed: %s\n",
1305                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1306                           win_errstr(werr)));
1307         }
1308         switch (reply_result) {
1309         case 0:
1310                 break;
1311         case PRINTER_NOTIFY_INFO_DISCARDED:
1312         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1313         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1314                 break;
1315         default:
1316                 break;
1317         }
1318
1319         return 0;
1320 }
1321
1322 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1323 {
1324         struct printer_handle    *p;
1325         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1326         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1327         int ret;
1328
1329         if ( !msg_group ) {
1330                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1331                 return;
1332         }
1333
1334         if (!msg_group->msgs) {
1335                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1336                 return;
1337         }
1338
1339         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1340
1341         /* loop over all printers */
1342
1343         for (p = printers_list; p; p = p->next) {
1344                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1345                 if (ret) {
1346                         goto done;
1347                 }
1348         }
1349
1350 done:
1351         DEBUG(8,("send_notify2_changes: Exit...\n"));
1352         return;
1353 }
1354
1355 /***********************************************************************
1356  **********************************************************************/
1357
1358 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1359 {
1360
1361         uint32_t tv_sec, tv_usec;
1362         size_t offset = 0;
1363
1364         /* Unpack message */
1365
1366         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1367                              msg->printer);
1368
1369         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1370                                 &tv_sec, &tv_usec,
1371                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1372
1373         if (msg->len == 0)
1374                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1375                            &msg->notify.value[0], &msg->notify.value[1]);
1376         else
1377                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1378                            &msg->len, &msg->notify.data);
1379
1380         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1381                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1382
1383         tv->tv_sec = tv_sec;
1384         tv->tv_usec = tv_usec;
1385
1386         if (msg->len == 0)
1387                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1388                           msg->notify.value[1]));
1389         else
1390                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1391
1392         return true;
1393 }
1394
1395 /********************************************************************
1396  Receive a notify2 message list
1397  ********************************************************************/
1398
1399 static void receive_notify2_message_list(struct messaging_context *msg,
1400                                          void *private_data,
1401                                          uint32_t msg_type,
1402                                          struct server_id server_id,
1403                                          DATA_BLOB *data)
1404 {
1405         size_t                  msg_count, i;
1406         char                    *buf = (char *)data->data;
1407         char                    *msg_ptr;
1408         size_t                  msg_len;
1409         SPOOLSS_NOTIFY_MSG      notify;
1410         SPOOLSS_NOTIFY_MSG_CTR  messages;
1411         int                     num_groups;
1412
1413         if (data->length < 4) {
1414                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1415                 return;
1416         }
1417
1418         msg_count = IVAL(buf, 0);
1419         msg_ptr = buf + 4;
1420
1421         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1422
1423         if (msg_count == 0) {
1424                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1425                 return;
1426         }
1427
1428         /* initialize the container */
1429
1430         ZERO_STRUCT( messages );
1431         notify_msg_ctr_init( &messages );
1432
1433         /*
1434          * build message groups for each printer identified
1435          * in a change_notify msg.  Remember that a PCN message
1436          * includes the handle returned for the srv_spoolss_replyopenprinter()
1437          * call.  Therefore messages are grouped according to printer handle.
1438          */
1439
1440         for ( i=0; i<msg_count; i++ ) {
1441                 struct timeval msg_tv;
1442
1443                 if (msg_ptr + 4 - buf > data->length) {
1444                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1445                         return;
1446                 }
1447
1448                 msg_len = IVAL(msg_ptr,0);
1449                 msg_ptr += 4;
1450
1451                 if (msg_ptr + msg_len - buf > data->length) {
1452                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1453                         return;
1454                 }
1455
1456                 /* unpack messages */
1457
1458                 ZERO_STRUCT( notify );
1459                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1460                 msg_ptr += msg_len;
1461
1462                 /* add to correct list in container */
1463
1464                 notify_msg_ctr_addmsg( &messages, &notify );
1465
1466                 /* free memory that might have been allocated by notify2_unpack_msg() */
1467
1468                 if ( notify.len != 0 )
1469                         SAFE_FREE( notify.notify.data );
1470         }
1471
1472         /* process each group of messages */
1473
1474         num_groups = notify_msg_ctr_numgroups( &messages );
1475         for ( i=0; i<num_groups; i++ )
1476                 send_notify2_changes( &messages, i );
1477
1478
1479         /* cleanup */
1480
1481         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1482                 (uint32_t)msg_count ));
1483
1484         notify_msg_ctr_destroy( &messages );
1485
1486         return;
1487 }
1488
1489 /********************************************************************
1490  Send a message to ourself about new driver being installed
1491  so we can upgrade the information for each printer bound to this
1492  driver
1493  ********************************************************************/
1494
1495 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1496                                             struct messaging_context *msg_ctx)
1497 {
1498         int len = strlen(drivername);
1499
1500         if (!len)
1501                 return false;
1502
1503         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1504                 drivername));
1505
1506         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1507                            MSG_PRINTER_DRVUPGRADE,
1508                            (const uint8_t *)drivername, len+1);
1509
1510         return true;
1511 }
1512
1513 void srv_spoolss_cleanup(void)
1514 {
1515         struct printer_session_counter *session_counter;
1516
1517         for (session_counter = counter_list;
1518              session_counter != NULL;
1519              session_counter = counter_list) {
1520                 DLIST_REMOVE(counter_list, session_counter);
1521                 TALLOC_FREE(session_counter);
1522         }
1523 }
1524
1525 /**********************************************************************
1526  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1527  over all printers, upgrading ones as necessary
1528  **********************************************************************/
1529
1530 void do_drv_upgrade_printer(struct messaging_context *msg,
1531                             void *private_data,
1532                             uint32_t msg_type,
1533                             struct server_id server_id,
1534                             DATA_BLOB *data)
1535 {
1536         TALLOC_CTX *tmp_ctx;
1537         struct auth_serversupplied_info *session_info = NULL;
1538         struct spoolss_PrinterInfo2 *pinfo2;
1539         NTSTATUS status;
1540         WERROR result;
1541         const char *drivername;
1542         int snum;
1543         int n_services = lp_numservices();
1544
1545         tmp_ctx = talloc_new(NULL);
1546         if (!tmp_ctx) return;
1547
1548         status = make_session_info_system(tmp_ctx, &session_info);
1549         if (!NT_STATUS_IS_OK(status)) {
1550                 DEBUG(0, ("do_drv_upgrade_printer: "
1551                           "Could not create system session_info\n"));
1552                 goto done;
1553         }
1554
1555         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1556         if (!drivername) {
1557                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1558                 goto done;
1559         }
1560
1561         DEBUG(10, ("do_drv_upgrade_printer: "
1562                    "Got message for new driver [%s]\n", drivername));
1563
1564         /* Iterate the printer list */
1565
1566         for (snum = 0; snum < n_services; snum++) {
1567                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1568                         continue;
1569                 }
1570
1571                 /* ignore [printers] share */
1572                 if (strequal(lp_const_servicename(snum), "printers")) {
1573                         continue;
1574                 }
1575
1576                 result = winreg_get_printer(tmp_ctx, session_info, msg,
1577                                             lp_const_servicename(snum),
1578                                             &pinfo2);
1579
1580                 if (!W_ERROR_IS_OK(result)) {
1581                         continue;
1582                 }
1583
1584                 if (!pinfo2->drivername) {
1585                         continue;
1586                 }
1587
1588                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1589                         continue;
1590                 }
1591
1592                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1593
1594                 /* all we care about currently is the change_id */
1595                 result = winreg_printer_update_changeid(tmp_ctx,
1596                                                         session_info,
1597                                                         msg,
1598                                                         pinfo2->printername);
1599
1600                 if (!W_ERROR_IS_OK(result)) {
1601                         DEBUG(3, ("do_drv_upgrade_printer: "
1602                                   "Failed to update changeid [%s]\n",
1603                                   win_errstr(result)));
1604                 }
1605         }
1606
1607         /* all done */
1608 done:
1609         talloc_free(tmp_ctx);
1610 }
1611
1612 /********************************************************************
1613  Update the cache for all printq's with a registered client
1614  connection
1615  ********************************************************************/
1616
1617 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1618 {
1619         struct printer_handle *printer = printers_list;
1620         int snum;
1621
1622         /* loop through all printers and update the cache where
1623            a client is connected */
1624         while (printer) {
1625                 if ((printer->printer_type == SPLHND_PRINTER) &&
1626                     ((printer->notify.cli_chan != NULL) &&
1627                      (printer->notify.cli_chan->active_connections > 0))) {
1628                         snum = print_queue_snum(printer->sharename);
1629                         print_queue_status(msg_ctx, snum, NULL, NULL);
1630                 }
1631
1632                 printer = printer->next;
1633         }
1634
1635         return;
1636 }
1637
1638 /****************************************************************
1639  _spoolss_OpenPrinter
1640 ****************************************************************/
1641
1642 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1643                             struct spoolss_OpenPrinter *r)
1644 {
1645         struct spoolss_OpenPrinterEx e;
1646         WERROR werr;
1647
1648         ZERO_STRUCT(e.in.userlevel);
1649
1650         e.in.printername        = r->in.printername;
1651         e.in.datatype           = r->in.datatype;
1652         e.in.devmode_ctr        = r->in.devmode_ctr;
1653         e.in.access_mask        = r->in.access_mask;
1654         e.in.level              = 0;
1655
1656         e.out.handle            = r->out.handle;
1657
1658         werr = _spoolss_OpenPrinterEx(p, &e);
1659
1660         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1661                 /* OpenPrinterEx returns this for a bad
1662                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1663                  * instead.
1664                  */
1665                 werr = WERR_INVALID_PRINTER_NAME;
1666         }
1667
1668         return werr;
1669 }
1670
1671 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1672                               struct spoolss_DeviceMode *orig,
1673                               struct spoolss_DeviceMode **dest)
1674 {
1675         struct spoolss_DeviceMode *dm;
1676
1677         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1678         if (!dm) {
1679                 return WERR_NOMEM;
1680         }
1681
1682         /* copy all values, then duplicate strings and structs */
1683         *dm = *orig;
1684
1685         dm->devicename = talloc_strdup(dm, orig->devicename);
1686         if (!dm->devicename) {
1687                 return WERR_NOMEM;
1688         }
1689         dm->formname = talloc_strdup(dm, orig->formname);
1690         if (!dm->formname) {
1691                 return WERR_NOMEM;
1692         }
1693         if (orig->driverextra_data.data) {
1694                 dm->driverextra_data.data =
1695                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1696                                         orig->driverextra_data.length);
1697                 if (!dm->driverextra_data.data) {
1698                         return WERR_NOMEM;
1699                 }
1700         }
1701
1702         *dest = dm;
1703         return WERR_OK;
1704 }
1705
1706 /****************************************************************
1707  _spoolss_OpenPrinterEx
1708 ****************************************************************/
1709
1710 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1711                               struct spoolss_OpenPrinterEx *r)
1712 {
1713         int snum;
1714         struct printer_handle *Printer=NULL;
1715         WERROR result;
1716
1717         if (!r->in.printername) {
1718                 return WERR_INVALID_PARAM;
1719         }
1720
1721         if (r->in.level > 3) {
1722                 return WERR_INVALID_PARAM;
1723         }
1724         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1725             (r->in.level == 2 && !r->in.userlevel.level2) ||
1726             (r->in.level == 3 && !r->in.userlevel.level3)) {
1727                 return WERR_INVALID_PARAM;
1728         }
1729
1730         /* some sanity check because you can open a printer or a print server */
1731         /* aka: \\server\printer or \\server */
1732
1733         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1734
1735         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1736         if (!W_ERROR_IS_OK(result)) {
1737                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1738                         "for printer %s\n", r->in.printername));
1739                 ZERO_STRUCTP(r->out.handle);
1740                 return result;
1741         }
1742
1743         Printer = find_printer_index_by_hnd(p, r->out.handle);
1744         if ( !Printer ) {
1745                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1746                         "handle we created for printer %s\n", r->in.printername));
1747                 close_printer_handle(p, r->out.handle);
1748                 ZERO_STRUCTP(r->out.handle);
1749                 return WERR_INVALID_PARAM;
1750         }
1751
1752         /*
1753          * First case: the user is opening the print server:
1754          *
1755          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1756          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1757          *
1758          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1759          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1760          * or if the user is listed in the smb.conf printer admin parameter.
1761          *
1762          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1763          * client view printer folder, but does not show the MSAPW.
1764          *
1765          * Note: this test needs code to check access rights here too. Jeremy
1766          * could you look at this?
1767          *
1768          * Second case: the user is opening a printer:
1769          * NT doesn't let us connect to a printer if the connecting user
1770          * doesn't have print permission.
1771          *
1772          * Third case: user is opening a Port Monitor
1773          * access checks same as opening a handle to the print server.
1774          */
1775
1776         switch (Printer->printer_type )
1777         {
1778         case SPLHND_SERVER:
1779         case SPLHND_PORTMON_TCP:
1780         case SPLHND_PORTMON_LOCAL:
1781                 /* Printserver handles use global struct... */
1782
1783                 snum = -1;
1784
1785                 /* Map standard access rights to object specific access rights */
1786
1787                 se_map_standard(&r->in.access_mask,
1788                                 &printserver_std_mapping);
1789
1790                 /* Deny any object specific bits that don't apply to print
1791                    servers (i.e printer and job specific bits) */
1792
1793                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1794
1795                 if (r->in.access_mask &
1796                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1797                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1798                         close_printer_handle(p, r->out.handle);
1799                         ZERO_STRUCTP(r->out.handle);
1800                         return WERR_ACCESS_DENIED;
1801                 }
1802
1803                 /* Allow admin access */
1804
1805                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1806                 {
1807                         if (!lp_ms_add_printer_wizard()) {
1808                                 close_printer_handle(p, r->out.handle);
1809                                 ZERO_STRUCTP(r->out.handle);
1810                                 return WERR_ACCESS_DENIED;
1811                         }
1812
1813                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1814                            and not a printer admin, then fail */
1815
1816                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1817                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1818                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1819                             !token_contains_name_in_list(
1820                                     uidtoname(p->session_info->utok.uid),
1821                                     p->session_info->info3->base.domain.string,
1822                                     NULL,
1823                                     p->session_info->security_token,
1824                                     lp_printer_admin(snum))) {
1825                                 close_printer_handle(p, r->out.handle);
1826                                 ZERO_STRUCTP(r->out.handle);
1827                                 DEBUG(3,("access DENIED as user is not root, "
1828                                         "has no printoperator privilege, "
1829                                         "not a member of the printoperator builtin group and "
1830                                         "is not in printer admin list"));
1831                                 return WERR_ACCESS_DENIED;
1832                         }
1833
1834                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1835                 }
1836                 else
1837                 {
1838                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1839                 }
1840
1841                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1842                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1843
1844                 /* We fall through to return WERR_OK */
1845                 break;
1846
1847         case SPLHND_PRINTER:
1848                 /* NT doesn't let us connect to a printer if the connecting user
1849                    doesn't have print permission.  */
1850
1851                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1852                         close_printer_handle(p, r->out.handle);
1853                         ZERO_STRUCTP(r->out.handle);
1854                         return WERR_BADFID;
1855                 }
1856
1857                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1858                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1859                 }
1860
1861                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1862
1863                 /* map an empty access mask to the minimum access mask */
1864                 if (r->in.access_mask == 0x0)
1865                         r->in.access_mask = PRINTER_ACCESS_USE;
1866
1867                 /*
1868                  * If we are not serving the printer driver for this printer,
1869                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1870                  * will keep NT clients happy  --jerry
1871                  */
1872
1873                 if (lp_use_client_driver(snum)
1874                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1875                 {
1876                         r->in.access_mask = PRINTER_ACCESS_USE;
1877                 }
1878
1879                 /* check smb.conf parameters and the the sec_desc */
1880
1881                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1882                                   p->client_id->name, p->client_id->addr)) {
1883                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1884                         ZERO_STRUCTP(r->out.handle);
1885                         return WERR_ACCESS_DENIED;
1886                 }
1887
1888                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1889                                    p->session_info->security_token, snum) ||
1890                     !print_access_check(p->session_info,
1891                                         p->msg_ctx,
1892                                         snum,
1893                                         r->in.access_mask)) {
1894                         DEBUG(3, ("access DENIED for printer open\n"));
1895                         close_printer_handle(p, r->out.handle);
1896                         ZERO_STRUCTP(r->out.handle);
1897                         return WERR_ACCESS_DENIED;
1898                 }
1899
1900                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1901                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1902                         close_printer_handle(p, r->out.handle);
1903                         ZERO_STRUCTP(r->out.handle);
1904                         return WERR_ACCESS_DENIED;
1905                 }
1906
1907                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1908                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1909                 else
1910                         r->in.access_mask = PRINTER_ACCESS_USE;
1911
1912                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1913                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1914
1915                 winreg_create_printer(p->mem_ctx,
1916                                       get_session_info_system(),
1917                                       p->msg_ctx,
1918                                       lp_const_servicename(snum));
1919
1920                 break;
1921
1922         default:
1923                 /* sanity check to prevent programmer error */
1924                 ZERO_STRUCTP(r->out.handle);
1925                 return WERR_BADFID;
1926         }
1927
1928         Printer->access_granted = r->in.access_mask;
1929
1930         /*
1931          * If the client sent a devmode in the OpenPrinter() call, then
1932          * save it here in case we get a job submission on this handle
1933          */
1934
1935          if ((Printer->printer_type != SPLHND_SERVER) &&
1936              r->in.devmode_ctr.devmode) {
1937                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1938                                 &Printer->devmode);
1939          }
1940
1941 #if 0   /* JERRY -- I'm doubtful this is really effective */
1942         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1943            optimization in Windows 2000 clients  --jerry */
1944
1945         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1946                 && (RA_WIN2K == get_remote_arch()) )
1947         {
1948                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1949                 sys_usleep( 500000 );
1950         }
1951 #endif
1952
1953         return WERR_OK;
1954 }
1955
1956 /****************************************************************
1957  _spoolss_ClosePrinter
1958 ****************************************************************/
1959
1960 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1961                              struct spoolss_ClosePrinter *r)
1962 {
1963         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1964
1965         if (Printer && Printer->document_started) {
1966                 struct spoolss_EndDocPrinter e;
1967
1968                 e.in.handle = r->in.handle;
1969
1970                 _spoolss_EndDocPrinter(p, &e);
1971         }
1972
1973         if (!close_printer_handle(p, r->in.handle))
1974                 return WERR_BADFID;
1975
1976         /* clear the returned printer handle.  Observed behavior
1977            from Win2k server.  Don't think this really matters.
1978            Previous code just copied the value of the closed
1979            handle.    --jerry */
1980
1981         ZERO_STRUCTP(r->out.handle);
1982
1983         return WERR_OK;
1984 }
1985
1986 /****************************************************************
1987  _spoolss_DeletePrinter
1988 ****************************************************************/
1989
1990 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1991                               struct spoolss_DeletePrinter *r)
1992 {
1993         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1994         WERROR result;
1995         int snum;
1996
1997         if (Printer && Printer->document_started) {
1998                 struct spoolss_EndDocPrinter e;
1999
2000                 e.in.handle = r->in.handle;
2001
2002                 _spoolss_EndDocPrinter(p, &e);
2003         }
2004
2005         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2006                 winreg_delete_printer_key(p->mem_ctx,
2007                                           get_session_info_system(),
2008                                           p->msg_ctx,
2009                                           lp_const_servicename(snum),
2010                                           "");
2011         }
2012
2013         result = delete_printer_handle(p, r->in.handle);
2014
2015         return result;
2016 }
2017
2018 /*******************************************************************
2019  * static function to lookup the version id corresponding to an
2020  * long architecture string
2021  ******************************************************************/
2022
2023 static const struct print_architecture_table_node archi_table[]= {
2024
2025         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2026         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2027         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2028         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2029         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2030         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2031         {"Windows x64",          SPL_ARCH_X64,          3 },
2032         {NULL,                   "",            -1 }
2033 };
2034
2035 static int get_version_id(const char *arch)
2036 {
2037         int i;
2038
2039         for (i=0; archi_table[i].long_archi != NULL; i++)
2040         {
2041                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2042                         return (archi_table[i].version);
2043         }
2044
2045         return -1;
2046 }
2047
2048 /****************************************************************
2049  _spoolss_DeletePrinterDriver
2050 ****************************************************************/
2051
2052 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2053                                     struct spoolss_DeletePrinterDriver *r)
2054 {
2055
2056         struct spoolss_DriverInfo8 *info = NULL;
2057         struct spoolss_DriverInfo8 *info_win2k = NULL;
2058         int                             version;
2059         WERROR                          status;
2060
2061         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2062            and not a printer admin, then fail */
2063
2064         if ( (p->session_info->utok.uid != sec_initial_uid())
2065              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2066                 && !token_contains_name_in_list(
2067                         uidtoname(p->session_info->utok.uid),
2068                         p->session_info->info3->base.domain.string,
2069                         NULL,
2070                         p->session_info->security_token,
2071                         lp_printer_admin(-1)) )
2072         {
2073                 return WERR_ACCESS_DENIED;
2074         }
2075
2076         /* check that we have a valid driver name first */
2077
2078         if ((version = get_version_id(r->in.architecture)) == -1)
2079                 return WERR_INVALID_ENVIRONMENT;
2080
2081         status = winreg_get_driver(p->mem_ctx,
2082                                    get_session_info_system(),
2083                                    p->msg_ctx,
2084                                    r->in.architecture, r->in.driver,
2085                                    version, &info);
2086         if (!W_ERROR_IS_OK(status)) {
2087                 /* try for Win2k driver if "Windows NT x86" */
2088
2089                 if ( version == 2 ) {
2090                         version = 3;
2091
2092                         status = winreg_get_driver(p->mem_ctx,
2093                                                    get_session_info_system(),
2094                                                    p->msg_ctx,
2095                                                    r->in.architecture,
2096                                                    r->in.driver,
2097                                                    version, &info);
2098                         if (!W_ERROR_IS_OK(status)) {
2099                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2100                                 goto done;
2101                         }
2102                 }
2103                 /* otherwise it was a failure */
2104                 else {
2105                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2106                         goto done;
2107                 }
2108
2109         }
2110
2111         if (printer_driver_in_use(p->mem_ctx,
2112                                   get_session_info_system(),
2113                                   p->msg_ctx,
2114                                   info)) {
2115                 status = WERR_PRINTER_DRIVER_IN_USE;
2116                 goto done;
2117         }
2118
2119         if (version == 2) {
2120                 status = winreg_get_driver(p->mem_ctx,
2121                                            get_session_info_system(),
2122                                            p->msg_ctx,
2123                                            r->in.architecture,
2124                                            r->in.driver, 3, &info_win2k);
2125                 if (W_ERROR_IS_OK(status)) {
2126                         /* if we get to here, we now have 2 driver info structures to remove */
2127                         /* remove the Win2k driver first*/
2128
2129                         status = winreg_del_driver(p->mem_ctx,
2130                                                    get_session_info_system(),
2131                                                    p->msg_ctx,
2132                                                    info_win2k, 3);
2133                         talloc_free(info_win2k);
2134
2135                         /* this should not have failed---if it did, report to client */
2136                         if (!W_ERROR_IS_OK(status)) {
2137                                 goto done;
2138                         }
2139                 }
2140         }
2141
2142         status = winreg_del_driver(p->mem_ctx,
2143                                    get_session_info_system(),
2144                                    p->msg_ctx,
2145                                    info, version);
2146
2147 done:
2148         talloc_free(info);
2149
2150         return status;
2151 }
2152
2153 /****************************************************************
2154  _spoolss_DeletePrinterDriverEx
2155 ****************************************************************/
2156
2157 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2158                                       struct spoolss_DeletePrinterDriverEx *r)
2159 {
2160         struct spoolss_DriverInfo8      *info = NULL;
2161         struct spoolss_DriverInfo8      *info_win2k = NULL;
2162         int                             version;
2163         bool                            delete_files;
2164         WERROR                          status;
2165
2166         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2167            and not a printer admin, then fail */
2168
2169         if ( (p->session_info->utok.uid != sec_initial_uid())
2170                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2171                 && !token_contains_name_in_list(
2172                         uidtoname(p->session_info->utok.uid),
2173                         p->session_info->info3->base.domain.string,
2174                         NULL,
2175                         p->session_info->security_token, lp_printer_admin(-1)) )
2176         {
2177                 return WERR_ACCESS_DENIED;
2178         }
2179
2180         /* check that we have a valid driver name first */
2181         if ((version = get_version_id(r->in.architecture)) == -1) {
2182                 /* this is what NT returns */
2183                 return WERR_INVALID_ENVIRONMENT;
2184         }
2185
2186         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2187                 version = r->in.version;
2188
2189         status = winreg_get_driver(p->mem_ctx,
2190                                    get_session_info_system(),
2191                                    p->msg_ctx,
2192                                    r->in.architecture,
2193                                    r->in.driver,
2194                                    version,
2195                                    &info);
2196         if (!W_ERROR_IS_OK(status)) {
2197                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2198
2199                 /*
2200                  * if the client asked for a specific version,
2201                  * or this is something other than Windows NT x86,
2202                  * then we've failed
2203                  */
2204
2205                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2206                         goto done;
2207
2208                 /* try for Win2k driver if "Windows NT x86" */
2209
2210                 version = 3;
2211                 status = winreg_get_driver(info,
2212                                            get_session_info_system(),
2213                                            p->msg_ctx,
2214                                            r->in.architecture,
2215                                            r->in.driver,
2216                                            version, &info);
2217                 if (!W_ERROR_IS_OK(status)) {
2218                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2219                         goto done;
2220                 }
2221         }
2222
2223         if (printer_driver_in_use(info,
2224                                   get_session_info_system(),
2225                                   p->msg_ctx,
2226                                   info)) {
2227                 status = WERR_PRINTER_DRIVER_IN_USE;
2228                 goto done;
2229         }
2230
2231         /*
2232          * we have a couple of cases to consider.
2233          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2234          *     then the delete should fail if **any** files overlap with
2235          *     other drivers
2236          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2237          *     non-overlapping files
2238          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2239          *     is set, the do not delete any files
2240          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2241          */
2242
2243         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2244
2245         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2246
2247         if (delete_files &&
2248             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2249             printer_driver_files_in_use(info,
2250                                         get_session_info_system(),
2251                                         p->msg_ctx,
2252                                         info)) {
2253                 /* no idea of the correct error here */
2254                 status = WERR_ACCESS_DENIED;
2255                 goto done;
2256         }
2257
2258
2259         /* also check for W32X86/3 if necessary; maybe we already have? */
2260
2261         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2262                 status = winreg_get_driver(info,
2263                                            get_session_info_system(),
2264                                            p->msg_ctx,
2265                                            r->in.architecture,
2266                                            r->in.driver, 3, &info_win2k);
2267                 if (W_ERROR_IS_OK(status)) {
2268
2269                         if (delete_files &&
2270                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2271                             printer_driver_files_in_use(info,
2272                                                         get_session_info_system(),
2273                                                         p->msg_ctx,
2274                                                         info_win2k)) {
2275                                 /* no idea of the correct error here */
2276                                 talloc_free(info_win2k);
2277                                 status = WERR_ACCESS_DENIED;
2278                                 goto done;
2279                         }
2280
2281                         /* if we get to here, we now have 2 driver info structures to remove */
2282                         /* remove the Win2k driver first*/
2283
2284                         status = winreg_del_driver(info,
2285                                                    get_session_info_system(),
2286                                                    p->msg_ctx,
2287                                                    info_win2k,
2288                                                    3);
2289
2290                         /* this should not have failed---if it did, report to client */
2291
2292                         if (!W_ERROR_IS_OK(status)) {
2293                                 goto done;
2294                         }
2295
2296                         /*
2297                          * now delete any associated files if delete_files is
2298                          * true. Even if this part failes, we return succes
2299                          * because the driver doesn not exist any more
2300                          */
2301                         if (delete_files) {
2302                                 delete_driver_files(get_session_info_system(),
2303                                                     info_win2k);
2304                         }
2305                 }
2306         }
2307
2308         status = winreg_del_driver(info,
2309                                    get_session_info_system(),
2310                                    p->msg_ctx,
2311                                    info,
2312                                    version);
2313         if (!W_ERROR_IS_OK(status)) {
2314                 goto done;
2315         }
2316
2317         /*
2318          * now delete any associated files if delete_files is
2319          * true. Even if this part failes, we return succes
2320          * because the driver doesn not exist any more
2321          */
2322         if (delete_files) {
2323                 delete_driver_files(get_session_info_system(), info);
2324         }
2325
2326 done:
2327         talloc_free(info);
2328         return status;
2329 }
2330
2331
2332 /********************************************************************
2333  GetPrinterData on a printer server Handle.
2334 ********************************************************************/
2335
2336 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2337                                             const char *value,
2338                                             enum winreg_Type *type,
2339                                             union spoolss_PrinterData *data)
2340 {
2341         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2342
2343         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2344                 *type = REG_DWORD;
2345                 data->value = 0x00;
2346                 return WERR_OK;
2347         }
2348
2349         if (!strcasecmp_m(value, "BeepEnabled")) {
2350                 *type = REG_DWORD;
2351                 data->value = 0x00;
2352                 return WERR_OK;
2353         }
2354
2355         if (!strcasecmp_m(value, "EventLog")) {
2356                 *type = REG_DWORD;
2357                 /* formally was 0x1b */
2358                 data->value = 0x00;
2359                 return WERR_OK;
2360         }
2361
2362         if (!strcasecmp_m(value, "NetPopup")) {
2363                 *type = REG_DWORD;
2364                 data->value = 0x00;
2365                 return WERR_OK;
2366         }
2367
2368         if (!strcasecmp_m(value, "MajorVersion")) {
2369                 *type = REG_DWORD;
2370
2371                 /* Windows NT 4.0 seems to not allow uploading of drivers
2372                    to a server that reports 0x3 as the MajorVersion.
2373                    need to investigate more how Win2k gets around this .
2374                    -- jerry */
2375
2376                 if (RA_WINNT == get_remote_arch()) {
2377                         data->value = 0x02;
2378                 } else {
2379                         data->value = 0x03;
2380                 }
2381
2382                 return WERR_OK;
2383         }
2384
2385         if (!strcasecmp_m(value, "MinorVersion")) {
2386                 *type = REG_DWORD;
2387                 data->value = 0x00;
2388                 return WERR_OK;
2389         }
2390
2391         /* REG_BINARY
2392          *  uint32_t size        = 0x114
2393          *  uint32_t major       = 5
2394          *  uint32_t minor       = [0|1]
2395          *  uint32_t build       = [2195|2600]
2396          *  extra unicode string = e.g. "Service Pack 3"
2397          */
2398         if (!strcasecmp_m(value, "OSVersion")) {
2399                 DATA_BLOB blob;
2400                 enum ndr_err_code ndr_err;
2401                 struct spoolss_OSVersion os;
2402
2403                 os.major                = 5;    /* Windows 2000 == 5.0 */
2404                 os.minor                = 0;
2405                 os.build                = 2195; /* build */
2406                 os.extra_string         = "";   /* leave extra string empty */
2407
2408                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2409                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2410                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2411                         return WERR_GENERAL_FAILURE;
2412                 }
2413
2414                 *type = REG_BINARY;
2415                 data->binary = blob;
2416
2417                 return WERR_OK;
2418         }
2419
2420
2421         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2422                 *type = REG_SZ;
2423
2424                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2425                 W_ERROR_HAVE_NO_MEMORY(data->string);
2426
2427                 return WERR_OK;
2428         }
2429
2430         if (!strcasecmp_m(value, "Architecture")) {
2431                 *type = REG_SZ;
2432                 data->string = talloc_strdup(mem_ctx,
2433                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2434                 W_ERROR_HAVE_NO_MEMORY(data->string);
2435
2436                 return WERR_OK;
2437         }
2438
2439         if (!strcasecmp_m(value, "DsPresent")) {
2440                 *type = REG_DWORD;
2441
2442                 /* only show the publish check box if we are a
2443                    member of a AD domain */
2444
2445                 if (lp_security() == SEC_ADS) {
2446                         data->value = 0x01;
2447                 } else {
2448                         data->value = 0x00;
2449                 }
2450                 return WERR_OK;
2451         }
2452
2453         if (!strcasecmp_m(value, "DNSMachineName")) {
2454                 const char *hostname = get_mydnsfullname();
2455
2456                 if (!hostname) {
2457                         return WERR_BADFILE;
2458                 }
2459
2460                 *type = REG_SZ;
2461                 data->string = talloc_strdup(mem_ctx, hostname);
2462                 W_ERROR_HAVE_NO_MEMORY(data->string);
2463
2464                 return WERR_OK;
2465         }
2466
2467         *type = REG_NONE;
2468
2469         return WERR_INVALID_PARAM;
2470 }
2471
2472 /****************************************************************
2473  _spoolss_GetPrinterData
2474 ****************************************************************/
2475
2476 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2477                                struct spoolss_GetPrinterData *r)
2478 {
2479         struct spoolss_GetPrinterDataEx r2;
2480
2481         r2.in.handle            = r->in.handle;
2482         r2.in.key_name          = "PrinterDriverData";
2483         r2.in.value_name        = r->in.value_name;
2484         r2.in.offered           = r->in.offered;
2485         r2.out.type             = r->out.type;
2486         r2.out.data             = r->out.data;
2487         r2.out.needed           = r->out.needed;
2488
2489         return _spoolss_GetPrinterDataEx(p, &r2);
2490 }
2491
2492 /*********************************************************
2493  Connect to the client machine.
2494 **********************************************************/
2495
2496 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2497                         struct sockaddr_storage *client_ss, const char *remote_machine)
2498 {
2499         NTSTATUS ret;
2500         struct cli_state *the_cli;
2501         struct sockaddr_storage rm_addr;
2502         char addr[INET6_ADDRSTRLEN];
2503
2504         if ( is_zero_addr(client_ss) ) {
2505                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2506                         remote_machine));
2507                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2508                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2509                         return false;
2510                 }
2511                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2512         } else {
2513                 rm_addr = *client_ss;
2514                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2515                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2516                         addr));
2517         }
2518
2519         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2520                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2521                         addr));
2522                 return false;
2523         }
2524
2525         /* setup the connection */
2526         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2527                 &rm_addr, 0, "IPC$", "IPC",
2528                 "", /* username */
2529                 "", /* domain */
2530                 "", /* password */
2531                 0, lp_client_signing());
2532
2533         if ( !NT_STATUS_IS_OK( ret ) ) {
2534                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2535                         remote_machine ));
2536                 return false;
2537         }
2538
2539         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2540                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2541                 cli_shutdown(the_cli);
2542                 return false;
2543         }
2544
2545         /*
2546          * Ok - we have an anonymous connection to the IPC$ share.
2547          * Now start the NT Domain stuff :-).
2548          */
2549
2550         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2551         if (!NT_STATUS_IS_OK(ret)) {
2552                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2553                         remote_machine, nt_errstr(ret)));
2554                 cli_shutdown(the_cli);
2555                 return false;
2556         }
2557
2558         return true;
2559 }
2560
2561 /***************************************************************************
2562  Connect to the client.
2563 ****************************************************************************/
2564
2565 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2566                                         uint32_t localprinter,
2567                                         enum winreg_Type type,
2568                                         struct policy_handle *handle,
2569                                         struct notify_back_channel **_chan,
2570                                         struct sockaddr_storage *client_ss,
2571                                         struct messaging_context *msg_ctx)
2572 {
2573         WERROR result;
2574         NTSTATUS status;
2575         struct notify_back_channel *chan;
2576
2577         for (chan = back_channels; chan; chan = chan->next) {
2578                 if (memcmp(&chan->client_address, client_ss,
2579                            sizeof(struct sockaddr_storage)) == 0) {
2580                         break;
2581                 }
2582         }
2583
2584         /*
2585          * If it's the first connection, contact the client
2586          * and connect to the IPC$ share anonymously
2587          */
2588         if (!chan) {
2589                 fstring unix_printer;
2590
2591                 /* the +2 is to strip the leading 2 backslashs */
2592                 fstrcpy(unix_printer, printer + 2);
2593
2594                 chan = talloc_zero(back_channels, struct notify_back_channel);
2595                 if (!chan) {
2596                         return false;
2597                 }
2598                 chan->client_address = *client_ss;
2599
2600                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2601                         TALLOC_FREE(chan);
2602                         return false;
2603                 }
2604                 chan->binding_handle = chan->cli_pipe->binding_handle;
2605
2606                 DLIST_ADD(back_channels, chan);
2607
2608                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2609                                    receive_notify2_message_list);
2610                 /* Tell the connections db we're now interested in printer
2611                  * notify messages. */
2612                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2613                                             true, FLAG_MSG_PRINT_NOTIFY);
2614         }
2615
2616         /*
2617          * Tell the specific printing tdb we want messages for this printer
2618          * by registering our PID.
2619          */
2620
2621         if (!print_notify_register_pid(snum)) {
2622                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2623                           printer));
2624         }
2625
2626         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2627                                                  talloc_tos(),
2628                                                  printer,
2629                                                  localprinter,
2630                                                  type,
2631                                                  0,
2632                                                  NULL,
2633                                                  handle,
2634                                                  &result);
2635         if (!NT_STATUS_IS_OK(status)) {
2636                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2637                 result = ntstatus_to_werror(status);
2638         } else if (!W_ERROR_IS_OK(result)) {
2639                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2640         }
2641
2642         chan->active_connections++;
2643         *_chan = chan;
2644
2645         return (W_ERROR_IS_OK(result));
2646 }
2647
2648 /****************************************************************
2649  ****************************************************************/
2650
2651 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2652                                                              const struct spoolss_NotifyOption *r)
2653 {
2654         struct spoolss_NotifyOption *option;
2655         uint32_t i,k;
2656
2657         if (!r) {
2658                 return NULL;
2659         }
2660
2661         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2662         if (!option) {
2663                 return NULL;
2664         }
2665
2666         *option = *r;
2667
2668         if (!option->count) {
2669                 return option;
2670         }
2671
2672         option->types = talloc_zero_array(option,
2673                 struct spoolss_NotifyOptionType, option->count);
2674         if (!option->types) {
2675                 talloc_free(option);
2676                 return NULL;
2677         }
2678
2679         for (i=0; i < option->count; i++) {
2680                 option->types[i] = r->types[i];
2681
2682                 if (option->types[i].count) {
2683                         option->types[i].fields = talloc_zero_array(option,
2684                                 union spoolss_Field, option->types[i].count);
2685                         if (!option->types[i].fields) {
2686                                 talloc_free(option);
2687                                 return NULL;
2688                         }
2689                         for (k=0; k<option->types[i].count; k++) {
2690                                 option->types[i].fields[k] =
2691                                         r->types[i].fields[k];
2692                         }
2693                 }
2694         }
2695
2696         return option;
2697 }
2698
2699 /****************************************************************
2700  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2701  *
2702  * before replying OK: status=0 a rpc call is made to the workstation
2703  * asking ReplyOpenPrinter
2704  *
2705  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2706  * called from api_spoolss_rffpcnex
2707 ****************************************************************/
2708
2709 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2710                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2711 {
2712         int snum = -1;
2713         struct spoolss_NotifyOption *option = r->in.notify_options;
2714         struct sockaddr_storage client_ss;
2715
2716         /* store the notify value in the printer struct */
2717
2718         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2719
2720         if (!Printer) {
2721                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2722                         "Invalid handle (%s:%u:%u).\n",
2723                         OUR_HANDLE(r->in.handle)));
2724                 return WERR_BADFID;
2725         }
2726
2727         Printer->notify.flags           = r->in.flags;
2728         Printer->notify.options         = r->in.options;
2729         Printer->notify.printerlocal    = r->in.printer_local;
2730         Printer->notify.msg_ctx         = p->msg_ctx;
2731
2732         TALLOC_FREE(Printer->notify.option);
2733         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2734
2735         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2736
2737         /* Connect to the client machine and send a ReplyOpenPrinter */
2738
2739         if ( Printer->printer_type == SPLHND_SERVER)
2740                 snum = -1;
2741         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2742                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2743                 return WERR_BADFID;
2744
2745         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2746                 "client_address is %s\n", p->client_id->addr));
2747
2748         if (!lp_print_notify_backchannel(snum)) {
2749                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2750                         "backchannel disabled\n"));
2751                 return WERR_SERVER_UNAVAILABLE;
2752         }
2753
2754         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2755                                    AI_NUMERICHOST)) {
2756                 return WERR_SERVER_UNAVAILABLE;
2757         }
2758
2759         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2760                                         Printer->notify.printerlocal, REG_SZ,
2761                                         &Printer->notify.cli_hnd,
2762                                         &Printer->notify.cli_chan,
2763                                         &client_ss, p->msg_ctx)) {
2764                 return WERR_SERVER_UNAVAILABLE;
2765         }
2766
2767         return WERR_OK;
2768 }
2769
2770 /*******************************************************************
2771  * fill a notify_info_data with the servername
2772  ********************************************************************/
2773
2774 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2775                                        int snum,
2776                                        struct spoolss_Notify *data,
2777                                        print_queue_struct *queue,
2778                                        struct spoolss_PrinterInfo2 *pinfo2,
2779                                        TALLOC_CTX *mem_ctx)
2780 {
2781         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2782 }
2783
2784 /*******************************************************************
2785  * fill a notify_info_data with the printername (not including the servername).
2786  ********************************************************************/
2787
2788 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2789                                         int snum,
2790                                         struct spoolss_Notify *data,
2791                                         print_queue_struct *queue,
2792                                         struct spoolss_PrinterInfo2 *pinfo2,
2793                                         TALLOC_CTX *mem_ctx)
2794 {
2795         /* the notify name should not contain the \\server\ part */
2796         const char *p = strrchr(pinfo2->printername, '\\');
2797
2798         if (!p) {
2799                 p = pinfo2->printername;
2800         } else {
2801                 p++;
2802         }
2803
2804         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2805 }
2806
2807 /*******************************************************************
2808  * fill a notify_info_data with the servicename
2809  ********************************************************************/
2810
2811 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2812                                       int snum,
2813                                       struct spoolss_Notify *data,
2814                                       print_queue_struct *queue,
2815                                       struct spoolss_PrinterInfo2 *pinfo2,
2816                                       TALLOC_CTX *mem_ctx)
2817 {
2818         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2819 }
2820
2821 /*******************************************************************
2822  * fill a notify_info_data with the port name
2823  ********************************************************************/
2824
2825 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2826                                      int snum,
2827                                      struct spoolss_Notify *data,
2828                                      print_queue_struct *queue,
2829                                      struct spoolss_PrinterInfo2 *pinfo2,
2830                                      TALLOC_CTX *mem_ctx)
2831 {
2832         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2833 }
2834
2835 /*******************************************************************
2836  * fill a notify_info_data with the printername
2837  * but it doesn't exist, have to see what to do
2838  ********************************************************************/
2839
2840 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2841                                        int snum,
2842                                        struct spoolss_Notify *data,
2843                                        print_queue_struct *queue,
2844                                        struct spoolss_PrinterInfo2 *pinfo2,
2845                                        TALLOC_CTX *mem_ctx)
2846 {
2847         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2848 }
2849
2850 /*******************************************************************
2851  * fill a notify_info_data with the comment
2852  ********************************************************************/
2853
2854 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2855                                    int snum,
2856                                    struct spoolss_Notify *data,
2857                                    print_queue_struct *queue,
2858                                    struct spoolss_PrinterInfo2 *pinfo2,
2859                                    TALLOC_CTX *mem_ctx)
2860 {
2861         const char *p;
2862
2863         if (*pinfo2->comment == '\0') {
2864                 p = lp_comment(snum);
2865         } else {
2866                 p = pinfo2->comment;
2867         }
2868
2869         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2870 }
2871
2872 /*******************************************************************
2873  * fill a notify_info_data with the comment
2874  * location = "Room 1, floor 2, building 3"
2875  ********************************************************************/
2876
2877 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2878                                     int snum,
2879                                     struct spoolss_Notify *data,
2880                                     print_queue_struct *queue,
2881                                     struct spoolss_PrinterInfo2 *pinfo2,
2882                                     TALLOC_CTX *mem_ctx)
2883 {
2884         const char *loc = pinfo2->location;
2885         NTSTATUS status;
2886
2887         status = printer_list_get_printer(mem_ctx,
2888                                           pinfo2->sharename,
2889                                           NULL,
2890                                           &loc,
2891                                           NULL);
2892         if (NT_STATUS_IS_OK(status)) {
2893                 if (loc == NULL) {
2894                         loc = pinfo2->location;
2895                 }
2896         }
2897
2898         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2899 }
2900
2901 /*******************************************************************
2902  * fill a notify_info_data with the device mode
2903  * jfm:xxxx don't to it for know but that's a real problem !!!
2904  ********************************************************************/
2905
2906 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2907                                    int snum,
2908                                    struct spoolss_Notify *data,
2909                                    print_queue_struct *queue,
2910                                    struct spoolss_PrinterInfo2 *pinfo2,
2911                                    TALLOC_CTX *mem_ctx)
2912 {
2913         /* for a dummy implementation we have to zero the fields */
2914         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2915 }
2916
2917 /*******************************************************************
2918  * fill a notify_info_data with the separator file name
2919  ********************************************************************/
2920
2921 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2922                                    int snum,
2923                                    struct spoolss_Notify *data,
2924                                    print_queue_struct *queue,
2925                                    struct spoolss_PrinterInfo2 *pinfo2,
2926                                    TALLOC_CTX *mem_ctx)
2927 {
2928         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2929 }
2930
2931 /*******************************************************************
2932  * fill a notify_info_data with the print processor
2933  * jfm:xxxx return always winprint to indicate we don't do anything to it
2934  ********************************************************************/
2935
2936 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2937                                            int snum,
2938                                            struct spoolss_Notify *data,
2939                                            print_queue_struct *queue,
2940                                            struct spoolss_PrinterInfo2 *pinfo2,
2941                                            TALLOC_CTX *mem_ctx)
2942 {
2943         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2944 }
2945
2946 /*******************************************************************
2947  * fill a notify_info_data with the print processor options
2948  * jfm:xxxx send an empty string
2949  ********************************************************************/
2950
2951 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2952                                       int snum,
2953                                       struct spoolss_Notify *data,
2954                                       print_queue_struct *queue,
2955                                       struct spoolss_PrinterInfo2 *pinfo2,
2956                                       TALLOC_CTX *mem_ctx)
2957 {
2958         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2959 }
2960
2961 /*******************************************************************
2962  * fill a notify_info_data with the data type
2963  * jfm:xxxx always send RAW as data type
2964  ********************************************************************/
2965
2966 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2967                                     int snum,
2968                                     struct spoolss_Notify *data,
2969                                     print_queue_struct *queue,
2970                                     struct spoolss_PrinterInfo2 *pinfo2,
2971                                     TALLOC_CTX *mem_ctx)
2972 {
2973         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2974 }
2975
2976 /*******************************************************************
2977  * fill a notify_info_data with the security descriptor
2978  * jfm:xxxx send an null pointer to say no security desc
2979  * have to implement security before !
2980  ********************************************************************/
2981
2982 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2983                                          int snum,
2984                                          struct spoolss_Notify *data,
2985                                          print_queue_struct *queue,
2986                                          struct spoolss_PrinterInfo2 *pinfo2,
2987                                          TALLOC_CTX *mem_ctx)
2988 {
2989         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2990 }
2991
2992 /*******************************************************************
2993  * fill a notify_info_data with the attributes
2994  * jfm:xxxx a samba printer is always shared
2995  ********************************************************************/
2996
2997 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2998                                       int snum,
2999                                       struct spoolss_Notify *data,
3000                                       print_queue_struct *queue,
3001                                       struct spoolss_PrinterInfo2 *pinfo2,
3002                                       TALLOC_CTX *mem_ctx)
3003 {
3004         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3005 }
3006
3007 /*******************************************************************
3008  * fill a notify_info_data with the priority
3009  ********************************************************************/
3010
3011 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3012                                     int snum,
3013                                     struct spoolss_Notify *data,
3014                                     print_queue_struct *queue,
3015                                     struct spoolss_PrinterInfo2 *pinfo2,
3016                                     TALLOC_CTX *mem_ctx)
3017 {
3018         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3019 }
3020
3021 /*******************************************************************
3022  * fill a notify_info_data with the default priority
3023  ********************************************************************/
3024
3025 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3026                                             int snum,
3027                                             struct spoolss_Notify *data,
3028                                             print_queue_struct *queue,
3029                                             struct spoolss_PrinterInfo2 *pinfo2,
3030                                             TALLOC_CTX *mem_ctx)
3031 {
3032         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3033 }
3034
3035 /*******************************************************************
3036  * fill a notify_info_data with the start time
3037  ********************************************************************/
3038
3039 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3040                                       int snum,
3041                                       struct spoolss_Notify *data,
3042                                       print_queue_struct *queue,
3043                                       struct spoolss_PrinterInfo2 *pinfo2,
3044                                       TALLOC_CTX *mem_ctx)
3045 {
3046         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3047 }
3048
3049 /*******************************************************************
3050  * fill a notify_info_data with the until time
3051  ********************************************************************/
3052
3053 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3054                                       int snum,
3055                                       struct spoolss_Notify *data,
3056                                       print_queue_struct *queue,
3057                                       struct spoolss_PrinterInfo2 *pinfo2,
3058                                       TALLOC_CTX *mem_ctx)
3059 {
3060         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3061 }
3062
3063 /*******************************************************************
3064  * fill a notify_info_data with the status
3065  ********************************************************************/
3066
3067 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3068                                   int snum,
3069                                   struct spoolss_Notify *data,
3070                                   print_queue_struct *queue,
3071                                   struct spoolss_PrinterInfo2 *pinfo2,
3072                                   TALLOC_CTX *mem_ctx)
3073 {
3074         print_status_struct status;
3075
3076         print_queue_length(msg_ctx, snum, &status);
3077         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3078 }
3079
3080 /*******************************************************************
3081  * fill a notify_info_data with the number of jobs queued
3082  ********************************************************************/
3083
3084 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3085                                  int snum,
3086                                  struct spoolss_Notify *data,
3087                                  print_queue_struct *queue,
3088                                  struct spoolss_PrinterInfo2 *pinfo2,
3089                                  TALLOC_CTX *mem_ctx)
3090 {
3091         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3092                 data, print_queue_length(msg_ctx, snum, NULL));
3093 }
3094
3095 /*******************************************************************
3096  * fill a notify_info_data with the average ppm
3097  ********************************************************************/
3098
3099 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3100                                        int snum,
3101                                        struct spoolss_Notify *data,
3102                                        print_queue_struct *queue,
3103                                        struct spoolss_PrinterInfo2 *pinfo2,
3104                                        TALLOC_CTX *mem_ctx)
3105 {
3106         /* always respond 8 pages per minutes */
3107         /* a little hard ! */
3108         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3109 }
3110
3111 /*******************************************************************
3112  * fill a notify_info_data with username
3113  ********************************************************************/
3114
3115 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3116                                     int snum,
3117                                     struct spoolss_Notify *data,
3118                                     print_queue_struct *queue,
3119                                     struct spoolss_PrinterInfo2 *pinfo2,
3120                                     TALLOC_CTX *mem_ctx)
3121 {
3122         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3123 }
3124
3125 /*******************************************************************
3126  * fill a notify_info_data with job status
3127  ********************************************************************/
3128
3129 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3130                                       int snum,
3131                                       struct spoolss_Notify *data,
3132                                       print_queue_struct *queue,
3133                                       struct spoolss_PrinterInfo2 *pinfo2,
3134                                       TALLOC_CTX *mem_ctx)
3135 {
3136         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3137 }
3138
3139 /*******************************************************************
3140  * fill a notify_info_data with job name
3141  ********************************************************************/
3142
3143 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3144                                     int snum,
3145                                     struct spoolss_Notify *data,
3146                                     print_queue_struct *queue,
3147                                     struct spoolss_PrinterInfo2 *pinfo2,
3148                                     TALLOC_CTX *mem_ctx)
3149 {
3150         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3151 }
3152
3153 /*******************************************************************
3154  * fill a notify_info_data with job status
3155  ********************************************************************/
3156
3157 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3158                                              int snum,
3159                                              struct spoolss_Notify *data,
3160                                              print_queue_struct *queue,
3161                                              struct spoolss_PrinterInfo2 *pinfo2,
3162                                              TALLOC_CTX *mem_ctx)
3163 {
3164         /*
3165          * Now we're returning job status codes we just return a "" here. JRA.
3166          */
3167
3168         const char *p = "";
3169
3170 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3171         p = "unknown";
3172
3173         switch (queue->status) {
3174         case LPQ_QUEUED:
3175                 p = "Queued";
3176                 break;
3177         case LPQ_PAUSED:
3178                 p = "";    /* NT provides the paused string */
3179                 break;
3180         case LPQ_SPOOLING:
3181                 p = "Spooling";
3182                 break;
3183         case LPQ_PRINTING:
3184                 p = "Printing";
3185                 break;
3186         }
3187 #endif /* NO LONGER NEEDED. */
3188
3189         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3190 }
3191
3192 /*******************************************************************
3193  * fill a notify_info_data with job time
3194  ********************************************************************/
3195
3196 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3197                                     int snum,
3198                                     struct spoolss_Notify *data,
3199                                     print_queue_struct *queue,
3200                                     struct spoolss_PrinterInfo2 *pinfo2,
3201                                     TALLOC_CTX *mem_ctx)
3202 {
3203         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3204 }
3205
3206 /*******************************************************************
3207  * fill a notify_info_data with job size
3208  ********************************************************************/
3209
3210 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3211                                     int snum,
3212                                     struct spoolss_Notify *data,
3213                                     print_queue_struct *queue,
3214                                     struct spoolss_PrinterInfo2 *pinfo2,
3215                                     TALLOC_CTX *mem_ctx)
3216 {
3217         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3218 }
3219
3220 /*******************************************************************
3221  * fill a notify_info_data with page info
3222  ********************************************************************/
3223 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3224                                        int snum,
3225                                 struct spoolss_Notify *data,
3226                                 print_queue_struct *queue,
3227                                 struct spoolss_PrinterInfo2 *pinfo2,
3228                                 TALLOC_CTX *mem_ctx)
3229 {
3230         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3231 }
3232
3233 /*******************************************************************
3234  * fill a notify_info_data with pages printed info.
3235  ********************************************************************/
3236 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3237                                          int snum,
3238                                 struct spoolss_Notify *data,
3239                                 print_queue_struct *queue,
3240                                 struct spoolss_PrinterInfo2 *pinfo2,
3241                                 TALLOC_CTX *mem_ctx)
3242 {
3243         /* Add code when back-end tracks this */
3244         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3245 }
3246
3247 /*******************************************************************
3248  Fill a notify_info_data with job position.
3249  ********************************************************************/
3250
3251 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3252                                         int snum,
3253                                         struct spoolss_Notify *data,
3254                                         print_queue_struct *queue,
3255                                         struct spoolss_PrinterInfo2 *pinfo2,
3256                                         TALLOC_CTX *mem_ctx)
3257 {
3258         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3259 }
3260
3261 /*******************************************************************
3262  Fill a notify_info_data with submitted time.
3263  ********************************************************************/
3264
3265 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3266                                           int snum,
3267                                           struct spoolss_Notify *data,
3268                                           print_queue_struct *queue,
3269                                           struct spoolss_PrinterInfo2 *pinfo2,
3270                                           TALLOC_CTX *mem_ctx)
3271 {
3272         data->data.string.string = NULL;
3273         data->data.string.size = 0;
3274
3275         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3276                                &data->data.string.string,
3277                                &data->data.string.size);
3278
3279 }
3280
3281 struct s_notify_info_data_table
3282 {
3283         enum spoolss_NotifyType type;
3284         uint16_t field;
3285         const char *name;
3286         enum spoolss_NotifyTable variable_type;
3287         void (*fn) (struct messaging_context *msg_ctx,
3288                     int snum, struct spoolss_Notify *data,
3289                     print_queue_struct *queue,
3290                     struct spoolss_PrinterInfo2 *pinfo2,
3291                     TALLOC_CTX *mem_ctx);
3292 };
3293
3294 /* A table describing the various print notification constants and
3295    whether the notification data is a pointer to a variable sized
3296    buffer, a one value uint32_t or a two value uint32_t. */
3297
3298 static const struct s_notify_info_data_table notify_info_data_table[] =
3299 {
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3323 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3324 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3325 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3326 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3327 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3328 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3329 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3330 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3331 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3332 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3333 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3334 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3335 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3336 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3337 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3338 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3339 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3340 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3341 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3342 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3343 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3344 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3345 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3346 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3347 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3348 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3349 };
3350
3351 /*******************************************************************
3352  Return the variable_type of info_data structure.
3353 ********************************************************************/
3354
3355 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3356                                                                   uint16_t field)
3357 {
3358         int i=0;
3359
3360         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3361                 if ( (notify_info_data_table[i].type == type) &&
3362                      (notify_info_data_table[i].field == field) ) {
3363                         return notify_info_data_table[i].variable_type;
3364                 }
3365         }
3366
3367         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3368
3369         return (enum spoolss_NotifyTable) 0;
3370 }
3371
3372 /****************************************************************************
3373 ****************************************************************************/
3374
3375 static bool search_notify(enum spoolss_NotifyType type,
3376                           uint16_t field,
3377                           int *value)
3378 {
3379         int i;
3380
3381         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3382                 if (notify_info_data_table[i].type == type &&
3383                     notify_info_data_table[i].field == field &&
3384                     notify_info_data_table[i].fn != NULL) {
3385                         *value = i;
3386                         return true;
3387                 }
3388         }
3389
3390         return false;
3391 }
3392
3393 /****************************************************************************
3394 ****************************************************************************/
3395
3396 static void construct_info_data(struct spoolss_Notify *info_data,
3397                                 enum spoolss_NotifyType type,
3398                                 uint16_t field, int id)
3399 {
3400         info_data->type                 = type;
3401         info_data->field.field          = field;
3402         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3403         info_data->job_id               = id;
3404 }
3405
3406 /*******************************************************************
3407  *
3408  * fill a notify_info struct with info asked
3409  *
3410  ********************************************************************/
3411
3412 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3413                                           struct printer_handle *print_hnd,
3414                                           struct spoolss_NotifyInfo *info,
3415                                           struct spoolss_PrinterInfo2 *pinfo2,
3416                                           int snum,
3417                                           const struct spoolss_NotifyOptionType *option_type,
3418                                           uint32_t id,
3419                                           TALLOC_CTX *mem_ctx)
3420 {
3421         int field_num,j;
3422         enum spoolss_NotifyType type;
3423         uint16_t field;
3424
3425         struct spoolss_Notify *current_data;
3426
3427         type = option_type->type;
3428
3429         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3430                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3431                 option_type->count, lp_servicename(snum)));
3432
3433         for(field_num=0; field_num < option_type->count; field_num++) {
3434                 field = option_type->fields[field_num].field;
3435
3436                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3437
3438                 if (!search_notify(type, field, &j) )
3439                         continue;
3440
3441                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3442                                                       struct spoolss_Notify,
3443                                                       info->count + 1);
3444                 if (info->notifies == NULL) {
3445                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3446                         return false;
3447                 }
3448
3449                 current_data = &info->notifies[info->count];
3450
3451                 construct_info_data(current_data, type, field, id);
3452
3453                 DEBUG(10, ("construct_notify_printer_info: "
3454                            "calling [%s]  snum=%d  printername=[%s])\n",
3455                            notify_info_data_table[j].name, snum,
3456                            pinfo2->printername));
3457
3458                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3459                                              NULL, pinfo2, mem_ctx);
3460
3461                 info->count++;
3462         }
3463
3464         return true;
3465 }
3466
3467 /*******************************************************************
3468  *
3469  * fill a notify_info struct with info asked
3470  *
3471  ********************************************************************/
3472
3473 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3474                                        print_queue_struct *queue,
3475                                        struct spoolss_NotifyInfo *info,
3476                                        struct spoolss_PrinterInfo2 *pinfo2,
3477                                        int snum,
3478                                        const struct spoolss_NotifyOptionType *option_type,
3479                                        uint32_t id,
3480                                        TALLOC_CTX *mem_ctx)
3481 {
3482         int field_num,j;
3483         enum spoolss_NotifyType type;
3484         uint16_t field;
3485         struct spoolss_Notify *current_data;
3486
3487         DEBUG(4,("construct_notify_jobs_info\n"));
3488
3489         type = option_type->type;
3490
3491         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3492                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3493                 option_type->count));
3494
3495         for(field_num=0; field_num<option_type->count; field_num++) {
3496                 field = option_type->fields[field_num].field;
3497
3498                 if (!search_notify(type, field, &j) )
3499                         continue;
3500
3501                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3502                                                       struct spoolss_Notify,
3503                                                       info->count + 1);
3504                 if (info->notifies == NULL) {
3505                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3506                         return false;
3507                 }
3508
3509                 current_data=&(info->notifies[info->count]);
3510
3511                 construct_info_data(current_data, type, field, id);
3512                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3513                                              queue, pinfo2, mem_ctx);
3514                 info->count++;
3515         }
3516
3517         return true;
3518 }
3519
3520 /*
3521  * JFM: The enumeration is not that simple, it's even non obvious.
3522  *
3523  * let's take an example: I want to monitor the PRINTER SERVER for
3524  * the printer's name and the number of jobs currently queued.
3525  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3526  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3527  *
3528  * I have 3 printers on the back of my server.
3529  *
3530  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3531  * structures.
3532  *   Number     Data                    Id
3533  *      1       printer 1 name          1
3534  *      2       printer 1 cjob          1
3535  *      3       printer 2 name          2
3536  *      4       printer 2 cjob          2
3537  *      5       printer 3 name          3
3538  *      6       printer 3 name          3
3539  *
3540  * that's the print server case, the printer case is even worse.
3541  */
3542
3543 /*******************************************************************
3544  *
3545  * enumerate all printers on the printserver
3546  * fill a notify_info struct with info asked
3547  *
3548  ********************************************************************/
3549
3550 static WERROR printserver_notify_info(struct pipes_struct *p,
3551                                       struct policy_handle *hnd,
3552                                       struct spoolss_NotifyInfo *info,
3553                                       TALLOC_CTX *mem_ctx)
3554 {
3555         int snum;
3556         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3557         int n_services=lp_numservices();
3558         int i;
3559         struct spoolss_NotifyOption *option;
3560         struct spoolss_NotifyOptionType option_type;
3561         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3562         WERROR result;
3563
3564         DEBUG(4,("printserver_notify_info\n"));
3565
3566         if (!Printer)
3567                 return WERR_BADFID;
3568
3569         option = Printer->notify.option;
3570
3571         info->version   = 2;
3572         info->notifies  = NULL;
3573         info->count     = 0;
3574
3575         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3576            sending a ffpcn() request first */
3577
3578         if ( !option )
3579                 return WERR_BADFID;
3580
3581         for (i=0; i<option->count; i++) {
3582                 option_type = option->types[i];
3583
3584                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3585                         continue;
3586
3587                 for (snum = 0; snum < n_services; snum++) {
3588                         if (!lp_browseable(snum) ||
3589                             !lp_snum_ok(snum) ||
3590                             !lp_print_ok(snum)) {
3591                                 continue; /* skip */
3592                         }
3593
3594                         /* Maybe we should use the SYSTEM session_info here... */
3595                         result = winreg_get_printer(mem_ctx,
3596                                                     get_session_info_system(),
3597                                                     p->msg_ctx,
3598                                                     lp_servicename(snum),
3599                                                     &pinfo2);
3600                         if (!W_ERROR_IS_OK(result)) {
3601                                 DEBUG(4, ("printserver_notify_info: "
3602                                           "Failed to get printer [%s]\n",
3603                                           lp_servicename(snum)));
3604                                 continue;
3605                         }
3606
3607
3608                         construct_notify_printer_info(p->msg_ctx,
3609                                                       Printer, info,
3610                                                       pinfo2, snum,
3611                                                       &option_type, snum,
3612                                                       mem_ctx);
3613
3614                         TALLOC_FREE(pinfo2);
3615                 }
3616         }
3617
3618 #if 0
3619         /*
3620          * Debugging information, don't delete.
3621          */
3622
3623         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3624         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3625         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3626
3627         for (i=0; i<info->count; i++) {
3628                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3629                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3630                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3631         }
3632 #endif
3633
3634         return WERR_OK;
3635 }
3636
3637 /*******************************************************************
3638  *
3639  * fill a notify_info struct with info asked
3640  *
3641  ********************************************************************/
3642
3643 static WERROR printer_notify_info(struct pipes_struct *p,
3644                                   struct policy_handle *hnd,
3645                                   struct spoolss_NotifyInfo *info,
3646                                   TALLOC_CTX *mem_ctx)
3647 {
3648         int snum;
3649         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3650         int i;
3651         uint32_t id;
3652         struct spoolss_NotifyOption *option;
3653         struct spoolss_NotifyOptionType option_type;
3654         int count,j;
3655         print_queue_struct *queue=NULL;
3656         print_status_struct status;
3657         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3658         WERROR result;
3659
3660         DEBUG(4,("printer_notify_info\n"));
3661
3662         if (!Printer)
3663                 return WERR_BADFID;
3664
3665         option = Printer->notify.option;
3666         id = 0x0;
3667
3668         info->version   = 2;
3669         info->notifies  = NULL;
3670         info->count     = 0;
3671
3672         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3673            sending a ffpcn() request first */
3674
3675         if ( !option )
3676                 return WERR_BADFID;
3677
3678         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3679                 return WERR_BADFID;
3680         }
3681
3682         /* Maybe we should use the SYSTEM session_info here... */
3683         result = winreg_get_printer(mem_ctx,
3684                                     get_session_info_system(),
3685                                     p->msg_ctx,
3686                                     lp_servicename(snum), &pinfo2);
3687         if (!W_ERROR_IS_OK(result)) {
3688                 return WERR_BADFID;
3689         }
3690
3691         for (i=0; i<option->count; i++) {
3692                 option_type = option->types[i];
3693
3694                 switch (option_type.type) {
3695                 case PRINTER_NOTIFY_TYPE:
3696                         if (construct_notify_printer_info(p->msg_ctx,
3697                                                           Printer, info,
3698                                                           pinfo2, snum,
3699                                                           &option_type, id,
3700                                                           mem_ctx)) {
3701                                 id--;
3702                         }
3703                         break;
3704
3705                 case JOB_NOTIFY_TYPE:
3706
3707                         count = print_queue_status(p->msg_ctx, snum, &queue,
3708                                                    &status);
3709
3710                         for (j=0; j<count; j++) {
3711                                 construct_notify_jobs_info(p->msg_ctx,
3712                                                            &queue[j], info,
3713                                                            pinfo2, snum,
3714                                                            &option_type,
3715                                                            queue[j].job,
3716                                                            mem_ctx);
3717                         }
3718
3719                         SAFE_FREE(queue);
3720                         break;
3721                 }
3722         }
3723
3724         /*
3725          * Debugging information, don't delete.
3726          */
3727         /*
3728         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3729         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3730         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3731
3732         for (i=0; i<info->count; i++) {
3733                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3734                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3735                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3736         }
3737         */
3738
3739         talloc_free(pinfo2);
3740         return WERR_OK;
3741 }
3742
3743 /****************************************************************
3744  _spoolss_RouterRefreshPrinterChangeNotify
3745 ****************************************************************/
3746
3747 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3748                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3749 {
3750         struct spoolss_NotifyInfo *info;
3751
3752         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3753         WERROR result = WERR_BADFID;
3754
3755         /* we always have a spoolss_NotifyInfo struct */
3756         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3757         if (!info) {
3758                 result = WERR_NOMEM;
3759                 goto done;
3760         }
3761
3762         *r->out.info = info;
3763
3764         if (!Printer) {
3765                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3766                         "Invalid handle (%s:%u:%u).\n",
3767                         OUR_HANDLE(r->in.handle)));
3768                 goto done;
3769         }
3770
3771         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3772
3773         /*
3774          *      We are now using the change value, and
3775          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3776          *      I don't have a global notification system, I'm sending back all the
3777          *      information even when _NOTHING_ has changed.
3778          */
3779
3780         /* We need to keep track of the change value to send back in
3781            RRPCN replies otherwise our updates are ignored. */
3782
3783         Printer->notify.fnpcn = true;
3784
3785         if (Printer->notify.cli_chan != NULL &&
3786             Printer->notify.cli_chan->active_connections > 0) {
3787                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3788                         "Saving change value in request [%x]\n",
3789                         r->in.change_low));
3790                 Printer->notify.change = r->in.change_low;
3791         }
3792
3793         /* just ignore the spoolss_NotifyOption */
3794
3795         switch (Printer->printer_type) {
3796                 case SPLHND_SERVER:
3797                         result = printserver_notify_info(p, r->in.handle,
3798                                                          info, p->mem_ctx);
3799                         break;
3800
3801                 case SPLHND_PRINTER:
3802                         result = printer_notify_info(p, r->in.handle,
3803                                                      info, p->mem_ctx);
3804                         break;
3805         }
3806
3807         Printer->notify.fnpcn = false;
3808
3809 done:
3810         return result;
3811 }
3812
3813 /********************************************************************
3814  ********************************************************************/
3815
3816 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3817                                  const char *servername,
3818                                  const char *printername,
3819                                  const char **printername_p)
3820 {
3821         /* FIXME: add lp_force_printername() */
3822
3823         if (servername == NULL) {
3824                 *printername_p = talloc_strdup(mem_ctx, printername);
3825                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3826                 return WERR_OK;
3827         }
3828
3829         if (servername[0] == '\\' && servername[1] == '\\') {
3830                 servername += 2;
3831         }
3832
3833         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3834         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3835
3836         return WERR_OK;
3837 }
3838
3839 /********************************************************************
3840  ********************************************************************/
3841
3842 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3843                                           const char *printername)
3844 {
3845         if (dm == NULL) {
3846                 return;
3847         }
3848
3849         dm->devicename = talloc_strndup(dm, printername,
3850                                         MIN(strlen(printername), 31));
3851 }
3852
3853 /********************************************************************
3854  * construct_printer_info_0
3855  * fill a printer_info_0 struct
3856  ********************************************************************/
3857
3858 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3859                                       const struct auth_serversupplied_info *session_info,
3860                                       struct messaging_context *msg_ctx,
3861                                       struct spoolss_PrinterInfo2 *info2,
3862                                       const char *servername,
3863                                       struct spoolss_PrinterInfo0 *r,
3864                                       int snum)
3865 {
3866         int count;
3867         struct printer_session_counter *session_counter;
3868         struct timeval setuptime;
3869         print_status_struct status;
3870         WERROR result;
3871
3872         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3873         if (!W_ERROR_IS_OK(result)) {
3874                 return result;
3875         }
3876
3877         if (servername) {
3878                 r->servername = talloc_strdup(mem_ctx, servername);
3879                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3880         } else {
3881                 r->servername = NULL;
3882         }
3883
3884         count = print_queue_length(msg_ctx, snum, &status);
3885
3886         /* check if we already have a counter for this printer */
3887         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3888                 if (session_counter->snum == snum)
3889                         break;
3890         }
3891
3892         /* it's the first time, add it to the list */
3893         if (session_counter == NULL) {
3894                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3895                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3896                 session_counter->snum           = snum;
3897                 session_counter->counter        = 0;
3898                 DLIST_ADD(counter_list, session_counter);
3899         }
3900
3901         /* increment it */
3902         session_counter->counter++;
3903
3904         r->cjobs                        = count;
3905         r->total_jobs                   = 0;
3906         r->total_bytes                  = 0;
3907
3908         get_startup_time(&setuptime);
3909         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3910
3911         /* JFM:
3912          * the global_counter should be stored in a TDB as it's common to all the clients
3913          * and should be zeroed on samba startup
3914          */
3915         r->global_counter               = session_counter->counter;
3916         r->total_pages                  = 0;
3917         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3918         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3919         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3920         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3921         r->spooling                     = 0;
3922         r->max_spooling                 = 0;
3923         r->session_counter              = session_counter->counter;
3924         r->num_error_out_of_paper       = 0x0;
3925         r->num_error_not_ready          = 0x0;          /* number of print failure */
3926         r->job_error                    = 0x0;
3927         r->number_of_processors         = 0x1;
3928         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3929         r->high_part_total_bytes        = 0x0;
3930
3931         /* ChangeID in milliseconds*/
3932         winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3933                                     info2->sharename, &r->change_id);
3934
3935         r->last_error                   = WERR_OK;
3936         r->status                       = nt_printq_status(status.status);
3937         r->enumerate_network_printers   = 0x0;
3938         r->c_setprinter                 = 0x0;
3939         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3940         r->processor_level              = 0x6;          /* 6  ???*/
3941         r->ref_ic                       = 0;
3942         r->reserved2                    = 0;
3943         r->reserved3                    = 0;
3944
3945         return WERR_OK;
3946 }
3947
3948
3949 /********************************************************************
3950  * construct_printer_info1
3951  * fill a spoolss_PrinterInfo1 struct
3952 ********************************************************************/
3953
3954 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3955                                       const struct spoolss_PrinterInfo2 *info2,
3956                                       uint32_t flags,
3957                                       const char *servername,
3958                                       struct spoolss_PrinterInfo1 *r,
3959                                       int snum)
3960 {
3961         WERROR result;
3962
3963         r->flags                = flags;
3964
3965         if (info2->comment == NULL || info2->comment[0] == '\0') {
3966                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3967         } else {
3968                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3969         }
3970         W_ERROR_HAVE_NO_MEMORY(r->comment);
3971
3972         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3973         if (!W_ERROR_IS_OK(result)) {
3974                 return result;
3975         }
3976
3977         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3978                                                   r->name,
3979                                                   info2->drivername,
3980                                                   r->comment);
3981         W_ERROR_HAVE_NO_MEMORY(r->description);
3982
3983         return WERR_OK;
3984 }
3985
3986 /********************************************************************
3987  * construct_printer_info2
3988  * fill a spoolss_PrinterInfo2 struct
3989 ********************************************************************/
3990
3991 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3992                                       struct messaging_context *msg_ctx,
3993                                       const struct spoolss_PrinterInfo2 *info2,
3994                                       const char *servername,
3995                                       struct spoolss_PrinterInfo2 *r,
3996                                       int snum)
3997 {
3998         int count;
3999         print_status_struct status;
4000         WERROR result;
4001
4002         count = print_queue_length(msg_ctx, snum, &status);
4003
4004         if (servername) {
4005                 r->servername           = talloc_strdup(mem_ctx, servername);
4006                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4007         } else {
4008                 r->servername           = NULL;
4009         }
4010
4011         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4012         if (!W_ERROR_IS_OK(result)) {
4013                 return result;
4014         }
4015
4016         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4017         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4018         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4019         W_ERROR_HAVE_NO_MEMORY(r->portname);
4020         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4021         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4022
4023         if (info2->comment[0] == '\0') {
4024                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4025         } else {
4026                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4027         }
4028         W_ERROR_HAVE_NO_MEMORY(r->comment);
4029
4030         r->location     = talloc_strdup(mem_ctx, info2->location);
4031         if (info2->location[0] == '\0') {
4032                 const char *loc = NULL;
4033                 NTSTATUS nt_status;
4034
4035                 nt_status = printer_list_get_printer(mem_ctx,
4036                                                      info2->sharename,
4037                                                      NULL,
4038                                                      &loc,
4039                                                      NULL);
4040                 if (NT_STATUS_IS_OK(nt_status)) {
4041                         if (loc != NULL) {
4042                                 r->location = talloc_strdup(mem_ctx, loc);
4043                         }
4044                 }
4045         }
4046         W_ERROR_HAVE_NO_MEMORY(r->location);
4047
4048         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4049         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4050         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4051         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4052         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4053         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4054         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4055         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4056
4057         r->attributes           = info2->attributes;
4058
4059         r->priority             = info2->priority;
4060         r->defaultpriority      = info2->defaultpriority;
4061         r->starttime            = info2->starttime;
4062         r->untiltime            = info2->untiltime;
4063         r->status               = nt_printq_status(status.status);
4064         r->cjobs                = count;
4065         r->averageppm           = info2->averageppm;
4066
4067         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4068         if (!r->devmode) {
4069                 DEBUG(8,("Returning NULL Devicemode!\n"));
4070         }
4071
4072         compose_devicemode_devicename(r->devmode, r->printername);
4073
4074         r->secdesc = NULL;
4075
4076         if (info2->secdesc != NULL) {
4077                 /* don't use talloc_steal() here unless you do a deep steal of all
4078                    the SEC_DESC members */
4079
4080                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4081         }
4082
4083         return WERR_OK;
4084 }
4085
4086 /********************************************************************
4087  * construct_printer_info3
4088  * fill a spoolss_PrinterInfo3 struct
4089  ********************************************************************/
4090
4091 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4092                                       const struct spoolss_PrinterInfo2 *info2,
4093                                       const char *servername,
4094                                       struct spoolss_PrinterInfo3 *r,
4095                                       int snum)
4096 {
4097         /* These are the components of the SD we are returning. */
4098
4099         if (info2->secdesc != NULL) {
4100                 /* don't use talloc_steal() here unless you do a deep steal of all
4101                    the SEC_DESC members */
4102
4103                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4104                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4105         }
4106
4107         return WERR_OK;
4108 }
4109
4110 /********************************************************************
4111  * construct_printer_info4
4112  * fill a spoolss_PrinterInfo4 struct
4113  ********************************************************************/
4114
4115 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4116                                       const struct spoolss_PrinterInfo2 *info2,
4117                                       const char *servername,
4118                                       struct spoolss_PrinterInfo4 *r,
4119                                       int snum)
4120 {
4121         WERROR result;
4122
4123         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4124         if (!W_ERROR_IS_OK(result)) {
4125                 return result;
4126         }
4127
4128         if (servername) {
4129                 r->servername   = talloc_strdup(mem_ctx, servername);
4130                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4131         } else {
4132                 r->servername = NULL;
4133         }
4134
4135         r->attributes   = info2->attributes;
4136
4137         return WERR_OK;
4138 }
4139
4140 /********************************************************************
4141  * construct_printer_info5
4142  * fill a spoolss_PrinterInfo5 struct
4143  ********************************************************************/
4144
4145 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4146                                       const struct spoolss_PrinterInfo2 *info2,
4147                                       const char *servername,
4148                                       struct spoolss_PrinterInfo5 *r,
4149                                       int snum)
4150 {
4151         WERROR result;
4152
4153         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4154         if (!W_ERROR_IS_OK(result)) {
4155                 return result;
4156         }
4157
4158         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4159         W_ERROR_HAVE_NO_MEMORY(r->portname);
4160
4161         r->attributes   = info2->attributes;
4162
4163         /* these two are not used by NT+ according to MSDN */
4164         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4165         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4166
4167         return WERR_OK;
4168 }
4169
4170 /********************************************************************
4171  * construct_printer_info_6
4172  * fill a spoolss_PrinterInfo6 struct
4173  ********************************************************************/
4174
4175 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4176                                       struct messaging_context *msg_ctx,
4177                                       const struct spoolss_PrinterInfo2 *info2,
4178                                       const char *servername,
4179                                       struct spoolss_PrinterInfo6 *r,
4180                                       int snum)
4181 {
4182         int count;
4183         print_status_struct status;
4184
4185         count = print_queue_length(msg_ctx, snum, &status);
4186
4187         r->status = nt_printq_status(status.status);
4188
4189         return WERR_OK;
4190 }
4191
4192 /********************************************************************
4193  * construct_printer_info7
4194  * fill a spoolss_PrinterInfo7 struct
4195  ********************************************************************/
4196
4197 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4198                                       struct messaging_context *msg_ctx,
4199                                       const char *servername,
4200                                       struct spoolss_PrinterInfo7 *r,
4201                                       int snum)
4202 {
4203         struct auth_serversupplied_info *session_info;
4204         struct GUID guid;
4205         NTSTATUS status;
4206
4207         status = make_session_info_system(mem_ctx, &session_info);
4208         if (!NT_STATUS_IS_OK(status)) {
4209                 DEBUG(0, ("construct_printer_info7: "
4210                           "Could not create system session_info\n"));
4211                 return WERR_NOMEM;
4212         }
4213
4214         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4215                                  servername,
4216                                  lp_servicename(snum), &guid, NULL)) {
4217                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4218                 r->action = DSPRINT_PUBLISH;
4219         } else {
4220                 r->guid = talloc_strdup(mem_ctx, "");
4221                 r->action = DSPRINT_UNPUBLISH;
4222         }
4223         W_ERROR_HAVE_NO_MEMORY(r->guid);
4224
4225         TALLOC_FREE(session_info);
4226         return WERR_OK;
4227 }
4228
4229 /********************************************************************
4230  * construct_printer_info8
4231  * fill a spoolss_PrinterInfo8 struct
4232  ********************************************************************/
4233
4234 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4235                                       const struct spoolss_PrinterInfo2 *info2,
4236                                       const char *servername,
4237                                       struct spoolss_DeviceModeInfo *r,
4238                                       int snum)
4239 {
4240         WERROR result;
4241         const char *printername;
4242
4243         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4244         if (!W_ERROR_IS_OK(result)) {
4245                 return result;
4246         }
4247
4248         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4249         if (!r->devmode) {
4250                 DEBUG(8,("Returning NULL Devicemode!\n"));
4251         }
4252
4253         compose_devicemode_devicename(r->devmode, printername);
4254
4255         return WERR_OK;
4256 }
4257
4258
4259 /********************************************************************
4260 ********************************************************************/
4261
4262 static bool snum_is_shared_printer(int snum)
4263 {
4264         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4265 }
4266
4267 /********************************************************************
4268  Spoolss_enumprinters.
4269 ********************************************************************/
4270
4271 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4272                                            const struct auth_serversupplied_info *session_info,
4273                                            struct messaging_context *msg_ctx,
4274                                            const char *servername,
4275                                            uint32_t level,
4276                                            uint32_t flags,
4277                                            union spoolss_PrinterInfo **info_p,
4278                                            uint32_t *count_p)
4279 {
4280         int snum;
4281         int n_services = lp_numservices();
4282         union spoolss_PrinterInfo *info = NULL;
4283         uint32_t count = 0;
4284         WERROR result = WERR_OK;
4285
4286         *count_p = 0;
4287         *info_p = NULL;
4288
4289         for (snum = 0; snum < n_services; snum++) {
4290
4291                 const char *printer;
4292                 struct spoolss_PrinterInfo2 *info2;
4293
4294                 if (!snum_is_shared_printer(snum)) {
4295                         continue;
4296                 }
4297
4298                 printer = lp_const_servicename(snum);
4299
4300                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4301                         printer, snum));
4302
4303                 result = winreg_create_printer(mem_ctx,
4304                                                session_info,
4305                                                msg_ctx,
4306                                                printer);
4307                 if (!W_ERROR_IS_OK(result)) {
4308                         goto out;
4309                 }
4310
4311                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4312                                             union spoolss_PrinterInfo,
4313                                             count + 1);
4314                 if (!info) {
4315                         result = WERR_NOMEM;
4316                         goto out;
4317                 }
4318
4319                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4320                                             printer, &info2);
4321                 if (!W_ERROR_IS_OK(result)) {
4322                         goto out;
4323                 }
4324
4325                 switch (level) {
4326                 case 0:
4327                         result = construct_printer_info0(info, session_info,
4328                                                          msg_ctx, info2,
4329                                                          servername,
4330                                                          &info[count].info0, snum);
4331                         break;
4332                 case 1:
4333                         result = construct_printer_info1(info, info2, flags,
4334                                                          servername,
4335                                                          &info[count].info1, snum);
4336                         break;
4337                 case 2:
4338                         result = construct_printer_info2(info, msg_ctx, info2,
4339                                                          servername,
4340                                                          &info[count].info2, snum);
4341                         break;
4342                 case 4:
4343                         result = construct_printer_info4(info, info2,
4344                                                          servername,
4345                                                          &info[count].info4, snum);
4346                         break;
4347                 case 5:
4348                         result = construct_printer_info5(info, info2,
4349                                                          servername,
4350                                                          &info[count].info5, snum);
4351                         break;
4352
4353                 default:
4354                         result = WERR_UNKNOWN_LEVEL;
4355                         goto out;
4356                 }
4357
4358                 if (!W_ERROR_IS_OK(result)) {
4359                         goto out;
4360                 }
4361
4362                 count++;
4363         }
4364
4365         *count_p = count;
4366         *info_p = info;
4367
4368  out:
4369         if (!W_ERROR_IS_OK(result)) {
4370                 TALLOC_FREE(info);
4371                 return result;
4372         }
4373
4374         *info_p = info;
4375
4376         return WERR_OK;
4377 }
4378
4379 /********************************************************************
4380  * handle enumeration of printers at level 0
4381  ********************************************************************/
4382
4383 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4384                                   const struct auth_serversupplied_info *session_info,
4385                                   struct messaging_context *msg_ctx,
4386                                   uint32_t flags,
4387                                   const char *servername,
4388                                   union spoolss_PrinterInfo **info,
4389                                   uint32_t *count)
4390 {
4391         DEBUG(4,("enum_all_printers_info_0\n"));
4392
4393         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4394                                             servername, 0, flags, info, count);
4395 }
4396
4397
4398 /********************************************************************
4399 ********************************************************************/
4400
4401 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4402                                        const struct auth_serversupplied_info *session_info,
4403                                        struct messaging_context *msg_ctx,
4404                                        const char *servername,
4405                                        uint32_t flags,
4406                                        union spoolss_PrinterInfo **info,
4407                                        uint32_t *count)
4408 {
4409         DEBUG(4,("enum_all_printers_info_1\n"));
4410
4411         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4412                                             servername, 1, flags, info, count);
4413 }
4414
4415 /********************************************************************
4416  enum_all_printers_info_1_local.
4417 *********************************************************************/
4418
4419 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4420                                              const struct auth_serversupplied_info *session_info,
4421                                              struct messaging_context *msg_ctx,
4422                                              const char *servername,
4423                                              union spoolss_PrinterInfo **info,
4424                                              uint32_t *count)
4425 {
4426         DEBUG(4,("enum_all_printers_info_1_local\n"));
4427
4428         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4429                                         servername, PRINTER_ENUM_ICON8, info, count);
4430 }
4431
4432 /********************************************************************
4433  enum_all_printers_info_1_name.
4434 *********************************************************************/
4435
4436 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4437                                             const struct auth_serversupplied_info *session_info,
4438                                             struct messaging_context *msg_ctx,
4439                                             const char *servername,
4440                                             union spoolss_PrinterInfo **info,
4441                                             uint32_t *count)
4442 {
4443         const char *s = servername;
4444
4445         DEBUG(4,("enum_all_printers_info_1_name\n"));
4446
4447         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4448                 s = servername + 2;
4449         }
4450
4451         if (!is_myname_or_ipaddr(s)) {
4452                 return WERR_INVALID_NAME;
4453         }
4454
4455         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4456                                         servername, PRINTER_ENUM_ICON8, info, count);
4457 }
4458
4459 /********************************************************************
4460  enum_all_printers_info_1_network.
4461 *********************************************************************/
4462
4463 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4464                                                const struct auth_serversupplied_info *session_info,
4465                                                struct messaging_context *msg_ctx,
4466                                                const char *servername,
4467                                                union spoolss_PrinterInfo **info,
4468                                                uint32_t *count)
4469 {
4470         const char *s = servername;
4471
4472         DEBUG(4,("enum_all_printers_info_1_network\n"));
4473
4474         /* If we respond to a enum_printers level 1 on our name with flags
4475            set to PRINTER_ENUM_REMOTE with a list of printers then these
4476            printers incorrectly appear in the APW browse list.
4477            Specifically the printers for the server appear at the workgroup
4478            level where all the other servers in the domain are
4479            listed. Windows responds to this call with a
4480            WERR_CAN_NOT_COMPLETE so we should do the same. */
4481
4482         if (servername[0] == '\\' && servername[1] == '\\') {
4483                  s = servername + 2;
4484         }
4485
4486         if (is_myname_or_ipaddr(s)) {
4487                  return WERR_CAN_NOT_COMPLETE;
4488         }
4489
4490         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4491                                         servername, PRINTER_ENUM_NAME, info, count);
4492 }
4493
4494 /********************************************************************
4495  * api_spoolss_enumprinters
4496  *
4497  * called from api_spoolss_enumprinters (see this to understand)
4498  ********************************************************************/
4499
4500 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4501                                        const struct auth_serversupplied_info *session_info,
4502                                        struct messaging_context *msg_ctx,
4503                                        const char *servername,
4504                                        union spoolss_PrinterInfo **info,
4505                                        uint32_t *count)
4506 {
4507         DEBUG(4,("enum_all_printers_info_2\n"));
4508
4509         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4510                                             servername, 2, 0, info, count);
4511 }
4512
4513 /********************************************************************
4514  * handle enumeration of printers at level 1
4515  ********************************************************************/
4516
4517 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4518                                   const struct auth_serversupplied_info *session_info,
4519                                   struct messaging_context *msg_ctx,
4520                                   uint32_t flags,
4521                                   const char *servername,
4522                                   union spoolss_PrinterInfo **info,
4523                                   uint32_t *count)
4524 {
4525         /* Not all the flags are equals */
4526
4527         if (flags & PRINTER_ENUM_LOCAL) {
4528                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4529                                                       msg_ctx, servername, info, count);
4530         }
4531
4532         if (flags & PRINTER_ENUM_NAME) {
4533                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4534                                                      msg_ctx, servername, info,
4535                                                      count);
4536         }
4537
4538         if (flags & PRINTER_ENUM_NETWORK) {
4539                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4540                                                         msg_ctx, servername, info,
4541                                                         count);
4542         }
4543
4544         return WERR_OK; /* NT4sp5 does that */
4545 }
4546
4547 /********************************************************************
4548  * handle enumeration of printers at level 2
4549  ********************************************************************/
4550
4551 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4552                                   const struct auth_serversupplied_info *session_info,
4553                                   struct messaging_context *msg_ctx,
4554                                   uint32_t flags,
4555                                   const char *servername,
4556                                   union spoolss_PrinterInfo **info,
4557                                   uint32_t *count)
4558 {
4559         if (flags & PRINTER_ENUM_LOCAL) {
4560
4561                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4562                                                 servername,
4563                                                 info, count);
4564         }
4565
4566         if (flags & PRINTER_ENUM_NAME) {
4567                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4568                         return WERR_INVALID_NAME;
4569                 }
4570
4571                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4572                                                 servername,
4573                                                 info, count);
4574         }
4575
4576         if (flags & PRINTER_ENUM_REMOTE) {
4577                 return WERR_UNKNOWN_LEVEL;
4578         }
4579
4580         return WERR_OK;
4581 }
4582
4583 /********************************************************************
4584  * handle enumeration of printers at level 4
4585  ********************************************************************/
4586
4587 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4588                                   const struct auth_serversupplied_info *session_info,
4589                                   struct messaging_context *msg_ctx,
4590                                   uint32_t flags,
4591                                   const char *servername,
4592                                   union spoolss_PrinterInfo **info,
4593                                   uint32_t *count)
4594 {
4595         DEBUG(4,("enum_all_printers_info_4\n"));
4596
4597         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4598                                             servername, 4, flags, info, count);
4599 }
4600
4601
4602 /********************************************************************
4603  * handle enumeration of printers at level 5
4604  ********************************************************************/
4605
4606 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4607                                   const struct auth_serversupplied_info *session_info,
4608                                   struct messaging_context *msg_ctx,
4609                                   uint32_t flags,
4610                                   const char *servername,
4611                                   union spoolss_PrinterInfo **info,
4612                                   uint32_t *count)
4613 {
4614         DEBUG(4,("enum_all_printers_info_5\n"));
4615
4616         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4617                                             servername, 5, flags, info, count);
4618 }
4619
4620 /****************************************************************
4621  _spoolss_EnumPrinters
4622 ****************************************************************/
4623
4624 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4625                              struct spoolss_EnumPrinters *r)
4626 {
4627         const struct auth_serversupplied_info *session_info = get_session_info_system();
4628         WERROR result;
4629
4630         /* that's an [in out] buffer */
4631
4632         if (!r->in.buffer && (r->in.offered != 0)) {
4633                 return WERR_INVALID_PARAM;
4634         }
4635
4636         DEBUG(4,("_spoolss_EnumPrinters\n"));
4637
4638         *r->out.needed = 0;
4639         *r->out.count = 0;
4640         *r->out.info = NULL;
4641
4642         /*
4643          * Level 1:
4644          *          flags==PRINTER_ENUM_NAME
4645          *           if name=="" then enumerates all printers
4646          *           if name!="" then enumerate the printer
4647          *          flags==PRINTER_ENUM_REMOTE
4648          *          name is NULL, enumerate printers
4649          * Level 2: name!="" enumerates printers, name can't be NULL
4650          * Level 3: doesn't exist
4651          * Level 4: does a local registry lookup
4652          * Level 5: same as Level 2
4653          */
4654
4655         if (r->in.server && r->in.server[0] == '\0') {
4656                 r->in.server = NULL;
4657         }
4658
4659         switch (r->in.level) {
4660         case 0:
4661                 result = enumprinters_level0(p->mem_ctx, session_info,
4662                                              p->msg_ctx, r->in.flags,
4663                                              r->in.server,
4664                                              r->out.info, r->out.count);
4665                 break;
4666         case 1:
4667                 result = enumprinters_level1(p->mem_ctx, session_info,
4668                                              p->msg_ctx, r->in.flags,
4669                                              r->in.server,
4670                                              r->out.info, r->out.count);
4671                 break;
4672         case 2:
4673                 result = enumprinters_level2(p->mem_ctx, session_info,
4674                                              p->msg_ctx, r->in.flags,
4675                                              r->in.server,
4676                                              r->out.info, r->out.count);
4677                 break;
4678         case 4:
4679                 result = enumprinters_level4(p->mem_ctx, session_info,
4680                                              p->msg_ctx, r->in.flags,
4681                                              r->in.server,
4682                                              r->out.info, r->out.count);
4683                 break;
4684         case 5:
4685                 result = enumprinters_level5(p->mem_ctx, session_info,
4686                                              p->msg_ctx, r->in.flags,
4687                                              r->in.server,
4688                                              r->out.info, r->out.count);
4689                 break;
4690         default:
4691                 return WERR_UNKNOWN_LEVEL;
4692         }
4693
4694         if (!W_ERROR_IS_OK(result)) {
4695                 return result;
4696         }
4697
4698         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4699                                                      spoolss_EnumPrinters,
4700                                                      *r->out.info, r->in.level,
4701                                                      *r->out.count);
4702         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4703         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4704
4705         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4706 }
4707
4708 /****************************************************************
4709  _spoolss_GetPrinter
4710 ****************************************************************/
4711
4712 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4713                            struct spoolss_GetPrinter *r)
4714 {
4715         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4716         struct spoolss_PrinterInfo2 *info2 = NULL;
4717         WERROR result = WERR_OK;
4718         int snum;
4719
4720         /* that's an [in out] buffer */
4721
4722         if (!r->in.buffer && (r->in.offered != 0)) {
4723                 return WERR_INVALID_PARAM;
4724         }
4725
4726         *r->out.needed = 0;
4727
4728         if (Printer == NULL) {
4729                 return WERR_BADFID;
4730         }
4731
4732         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4733                 return WERR_BADFID;
4734         }
4735
4736         result = winreg_get_printer(p->mem_ctx,
4737                                     get_session_info_system(),
4738                                     p->msg_ctx,
4739                                     lp_const_servicename(snum),
4740                                     &info2);
4741         if (!W_ERROR_IS_OK(result)) {
4742                 goto out;
4743         }
4744
4745         switch (r->in.level) {
4746         case 0:
4747                 result = construct_printer_info0(p->mem_ctx,
4748                                                  get_session_info_system(),
4749                                                  p->msg_ctx,
4750                                                  info2,
4751                                                  Printer->servername,
4752                                                  &r->out.info->info0,
4753                                                  snum);
4754                 break;
4755         case 1:
4756                 result = construct_printer_info1(p->mem_ctx, info2,
4757                                                  PRINTER_ENUM_ICON8,
4758                                                  Printer->servername,
4759                                                  &r->out.info->info1, snum);
4760                 break;
4761         case 2:
4762                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4763                                                  Printer->servername,
4764                                                  &r->out.info->info2, snum);
4765                 break;
4766         case 3:
4767                 result = construct_printer_info3(p->mem_ctx, info2,
4768                                                  Printer->servername,
4769                                                  &r->out.info->info3, snum);
4770                 break;
4771         case 4:
4772                 result = construct_printer_info4(p->mem_ctx, info2,
4773                                                  Printer->servername,
4774                                                  &r->out.info->info4, snum);
4775                 break;
4776         case 5:
4777                 result = construct_printer_info5(p->mem_ctx, info2,
4778                                                  Printer->servername,
4779                                                  &r->out.info->info5, snum);
4780                 break;
4781         case 6:
4782                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4783                                                  Printer->servername,
4784                                                  &r->out.info->info6, snum);
4785                 break;
4786         case 7:
4787                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4788                                                  Printer->servername,
4789                                                  &r->out.info->info7, snum);
4790                 break;
4791         case 8:
4792                 result = construct_printer_info8(p->mem_ctx, info2,
4793                                                  Printer->servername,
4794                                                  &r->out.info->info8, snum);
4795                 break;
4796         default:
4797                 result = WERR_UNKNOWN_LEVEL;
4798                 break;
4799         }
4800
4801  out:
4802         if (!W_ERROR_IS_OK(result)) {
4803                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4804                           r->in.level, win_errstr(result)));
4805                 TALLOC_FREE(r->out.info);
4806                 return result;
4807         }
4808
4809         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4810                                                r->out.info, r->in.level);
4811         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4812
4813         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4814 }
4815
4816 /********************************************************************
4817  ********************************************************************/
4818
4819 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4820         do { \
4821                 if (in && strlen(in)) { \
4822                         out = talloc_strdup(mem_ctx, in); \
4823                 } else { \
4824                         out = talloc_strdup(mem_ctx, ""); \
4825                 } \
4826                 W_ERROR_HAVE_NO_MEMORY(out); \
4827         } while (0);
4828
4829 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4830         do { \
4831                 if (in && strlen(in)) { \
4832                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4833                 } else { \
4834                         out = talloc_strdup(mem_ctx, ""); \
4835                 } \
4836                 W_ERROR_HAVE_NO_MEMORY(out); \
4837         } while (0);
4838
4839 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4840                                                   const char **string_array,
4841                                                   const char ***presult,
4842                                                   const char *cservername,
4843                                                   const char *arch,
4844                                                   int version)
4845 {
4846         int i, num_strings = 0;
4847         const char **array = NULL;
4848
4849         if (string_array == NULL) {
4850                 return WERR_INVALID_PARAMETER;
4851         }
4852
4853         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4854                 const char *str = NULL;
4855
4856                 if (cservername == NULL || arch == NULL) {
4857                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4858                 } else {
4859                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4860                 }
4861
4862                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4863                         TALLOC_FREE(array);
4864                         return WERR_NOMEM;
4865                 }
4866         }
4867
4868         if (i > 0) {
4869                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4870                              &array, &num_strings);
4871         }
4872
4873         if (presult) {
4874                 *presult = array;
4875         }
4876
4877         return WERR_OK;
4878 }
4879
4880 /********************************************************************
4881  * fill a spoolss_DriverInfo1 struct
4882  ********************************************************************/
4883
4884 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4885                                         struct spoolss_DriverInfo1 *r,
4886                                         const struct spoolss_DriverInfo8 *driver,
4887                                         const char *servername)
4888 {
4889         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4890         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4891
4892         return WERR_OK;
4893 }
4894
4895 /********************************************************************
4896  * fill a spoolss_DriverInfo2 struct
4897  ********************************************************************/
4898
4899 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4900                                         struct spoolss_DriverInfo2 *r,
4901                                         const struct spoolss_DriverInfo8 *driver,
4902                                         const char *servername)
4903
4904 {
4905         const char *cservername = canon_servername(servername);
4906
4907         r->version              = driver->version;
4908
4909         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4910         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4911         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4912         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4913
4914         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4915                                driver->architecture,
4916                                driver->version,
4917                                driver->driver_path,
4918                                r->driver_path);
4919
4920         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4921                                driver->architecture,
4922                                driver->version,
4923                                driver->data_file,
4924                                r->data_file);
4925
4926         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4927                                driver->architecture,
4928                                driver->version,
4929                                driver->config_file,
4930                                r->config_file);
4931
4932         return WERR_OK;
4933 }
4934
4935 /********************************************************************
4936  * fill a spoolss_DriverInfo3 struct
4937  ********************************************************************/
4938
4939 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4940                                         struct spoolss_DriverInfo3 *r,
4941                                         const struct spoolss_DriverInfo8 *driver,
4942                                         const char *servername)
4943 {
4944         const char *cservername = canon_servername(servername);
4945
4946         r->version              = driver->version;
4947
4948         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4949         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4950         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4951         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4952
4953         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4954                                driver->architecture,
4955                                driver->version,
4956                                driver->driver_path,
4957                                r->driver_path);
4958
4959         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4960                                driver->architecture,
4961                                driver->version,
4962                                driver->data_file,
4963                                r->data_file);
4964
4965         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4966                                driver->architecture,
4967                                driver->version,
4968                                driver->config_file,
4969                                r->config_file);
4970
4971         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4972                                driver->architecture,
4973                                driver->version,
4974                                driver->help_file,
4975                                r->help_file);
4976
4977         FILL_DRIVER_STRING(mem_ctx,
4978                            driver->monitor_name,
4979                            r->monitor_name);
4980
4981         FILL_DRIVER_STRING(mem_ctx,
4982                            driver->default_datatype,
4983                            r->default_datatype);
4984
4985         return string_array_from_driver_info(mem_ctx,
4986                                              driver->dependent_files,
4987                                              &r->dependent_files,
4988                                              cservername,
4989                                              driver->architecture,
4990                                              driver->version);
4991 }
4992
4993 /********************************************************************
4994  * fill a spoolss_DriverInfo4 struct
4995  ********************************************************************/
4996
4997 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4998                                         struct spoolss_DriverInfo4 *r,
4999                                         const struct spoolss_DriverInfo8 *driver,
5000                                         const char *servername)
5001 {
5002         const char *cservername = canon_servername(servername);
5003         WERROR result;
5004
5005         r->version              = driver->version;
5006
5007         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5008         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5009         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5010         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5011
5012         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5013                                driver->architecture,
5014                                driver->version,
5015                                driver->driver_path,
5016                                r->driver_path);
5017
5018         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5019                                driver->architecture,
5020                                driver->version,
5021                                driver->data_file,
5022                                r->data_file);
5023
5024         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5025                                driver->architecture,
5026                                driver->version,
5027                                driver->config_file,
5028                                r->config_file);
5029
5030         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5031                                driver->architecture,
5032                                driver->version,
5033                                driver->help_file,
5034                                r->help_file);
5035
5036         result = string_array_from_driver_info(mem_ctx,
5037                                                driver->dependent_files,
5038                                                &r->dependent_files,
5039                                                cservername,
5040                                                driver->architecture,
5041                                                driver->version);
5042         if (!W_ERROR_IS_OK(result)) {
5043                 return result;
5044         }
5045
5046         FILL_DRIVER_STRING(mem_ctx,
5047                            driver->monitor_name,
5048                            r->monitor_name);
5049
5050         FILL_DRIVER_STRING(mem_ctx,
5051                            driver->default_datatype,
5052                            r->default_datatype);
5053
5054
5055         result = string_array_from_driver_info(mem_ctx,
5056                                                driver->previous_names,
5057                                                &r->previous_names,
5058                                                NULL, NULL, 0);
5059
5060         return result;
5061 }
5062
5063 /********************************************************************
5064  * fill a spoolss_DriverInfo5 struct
5065  ********************************************************************/
5066
5067 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5068                                         struct spoolss_DriverInfo5 *r,
5069                                         const struct spoolss_DriverInfo8 *driver,
5070                                         const char *servername)
5071 {
5072         const char *cservername = canon_servername(servername);
5073
5074         r->version              = driver->version;
5075
5076         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5077         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5078         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5079         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5080
5081         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5082                                driver->architecture,
5083                                driver->version,
5084                                driver->driver_path,
5085                                r->driver_path);
5086
5087         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5088                                driver->architecture,
5089                                driver->version,
5090                                driver->data_file,
5091                                r->data_file);
5092
5093         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5094                                driver->architecture,
5095                                driver->version,
5096                                driver->config_file,
5097                                r->config_file);
5098
5099         r->driver_attributes    = 0;
5100         r->config_version       = 0;
5101         r->driver_version       = 0;
5102
5103         return WERR_OK;
5104 }
5105 /********************************************************************
5106  * fill a spoolss_DriverInfo6 struct
5107  ********************************************************************/
5108
5109 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5110                                         struct spoolss_DriverInfo6 *r,
5111                                         const struct spoolss_DriverInfo8 *driver,
5112                                         const char *servername)
5113 {
5114         const char *cservername = canon_servername(servername);
5115         WERROR result;
5116
5117         r->version              = driver->version;
5118
5119         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5120         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5121         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5122         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5123
5124         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5125                                driver->architecture,
5126                                driver->version,
5127                                driver->driver_path,
5128                                r->driver_path);
5129
5130         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5131                                driver->architecture,
5132                                driver->version,
5133                                driver->data_file,
5134                                r->data_file);
5135
5136         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5137                                driver->architecture,
5138                                driver->version,
5139                                driver->config_file,
5140                                r->config_file);
5141
5142         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5143                                driver->architecture,
5144                                driver->version,
5145                                driver->help_file,
5146                                r->help_file);
5147
5148         FILL_DRIVER_STRING(mem_ctx,
5149                            driver->monitor_name,
5150                            r->monitor_name);
5151
5152         FILL_DRIVER_STRING(mem_ctx,
5153                            driver->default_datatype,
5154                            r->default_datatype);
5155
5156         result = string_array_from_driver_info(mem_ctx,
5157                                                driver->dependent_files,
5158                                                &r->dependent_files,
5159                                                cservername,
5160                                                driver->architecture,
5161                                                driver->version);
5162         if (!W_ERROR_IS_OK(result)) {
5163                 return result;
5164         }
5165
5166         result = string_array_from_driver_info(mem_ctx,
5167                                                driver->previous_names,
5168                                                &r->previous_names,
5169                                                NULL, NULL, 0);
5170         if (!W_ERROR_IS_OK(result)) {
5171                 return result;
5172         }
5173
5174         r->driver_date          = driver->driver_date;
5175         r->driver_version       = driver->driver_version;
5176
5177         FILL_DRIVER_STRING(mem_ctx,
5178                            driver->manufacturer_name,
5179                            r->manufacturer_name);
5180         FILL_DRIVER_STRING(mem_ctx,
5181                            driver->manufacturer_url,
5182                            r->manufacturer_url);
5183         FILL_DRIVER_STRING(mem_ctx,
5184                            driver->hardware_id,
5185                            r->hardware_id);
5186         FILL_DRIVER_STRING(mem_ctx,
5187                            driver->provider,
5188                            r->provider);
5189
5190         return WERR_OK;
5191 }
5192
5193 /********************************************************************
5194  * fill a spoolss_DriverInfo8 struct
5195  ********************************************************************/
5196
5197 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5198                                         struct spoolss_DriverInfo8 *r,
5199                                         const struct spoolss_DriverInfo8 *driver,
5200                                         const char *servername)
5201 {
5202         const char *cservername = canon_servername(servername);
5203         WERROR result;
5204
5205         r->version              = driver->version;
5206
5207         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5208         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5209         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5210         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5211
5212         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5213                                driver->architecture,
5214                                driver->version,
5215                                driver->driver_path,
5216                                r->driver_path);
5217
5218         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5219                                driver->architecture,
5220                                driver->version,
5221                                driver->data_file,
5222                                r->data_file);
5223
5224         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5225                                driver->architecture,
5226                                driver->version,
5227                                driver->config_file,
5228                                r->config_file);
5229
5230         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5231                                driver->architecture,
5232                                driver->version,
5233                                driver->help_file,
5234                                r->help_file);
5235
5236         FILL_DRIVER_STRING(mem_ctx,
5237                            driver->monitor_name,
5238                            r->monitor_name);
5239
5240         FILL_DRIVER_STRING(mem_ctx,
5241                            driver->default_datatype,
5242                            r->default_datatype);
5243
5244         result = string_array_from_driver_info(mem_ctx,
5245                                                driver->dependent_files,
5246                                                &r->dependent_files,
5247                                                cservername,
5248                                                driver->architecture,
5249                                                driver->version);
5250         if (!W_ERROR_IS_OK(result)) {
5251                 return result;
5252         }
5253
5254         result = string_array_from_driver_info(mem_ctx,
5255                                                driver->previous_names,
5256                                                &r->previous_names,
5257                                                NULL, NULL, 0);
5258         if (!W_ERROR_IS_OK(result)) {
5259                 return result;
5260         }
5261
5262         r->driver_date          = driver->driver_date;
5263         r->driver_version       = driver->driver_version;
5264
5265         FILL_DRIVER_STRING(mem_ctx,
5266                            driver->manufacturer_name,
5267                            r->manufacturer_name);
5268         FILL_DRIVER_STRING(mem_ctx,
5269                            driver->manufacturer_url,
5270                            r->manufacturer_url);
5271         FILL_DRIVER_STRING(mem_ctx,
5272                            driver->hardware_id,
5273                            r->hardware_id);
5274         FILL_DRIVER_STRING(mem_ctx,
5275                            driver->provider,
5276                            r->provider);
5277
5278         FILL_DRIVER_STRING(mem_ctx,
5279                            driver->print_processor,
5280                            r->print_processor);
5281         FILL_DRIVER_STRING(mem_ctx,
5282                            driver->vendor_setup,
5283                            r->vendor_setup);
5284
5285         result = string_array_from_driver_info(mem_ctx,
5286                                                driver->color_profiles,
5287                                                &r->color_profiles,
5288                                                NULL, NULL, 0);
5289         if (!W_ERROR_IS_OK(result)) {
5290                 return result;
5291         }
5292
5293         FILL_DRIVER_STRING(mem_ctx,
5294                            driver->inf_path,
5295                            r->inf_path);
5296
5297         r->printer_driver_attributes    = driver->printer_driver_attributes;
5298
5299         result = string_array_from_driver_info(mem_ctx,
5300                                                driver->core_driver_dependencies,
5301                                                &r->core_driver_dependencies,
5302                                                NULL, NULL, 0);
5303         if (!W_ERROR_IS_OK(result)) {
5304                 return result;
5305         }
5306
5307         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5308         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5309
5310         return WERR_OK;
5311 }
5312
5313 #if 0 /* disabled until marshalling issues are resolved - gd */
5314 /********************************************************************
5315  ********************************************************************/
5316
5317 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5318                                           struct spoolss_DriverFileInfo *r,
5319                                           const char *cservername,
5320                                           const char *file_name,
5321                                           enum spoolss_DriverFileType file_type,
5322                                           uint32_t file_version)
5323 {
5324         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5325                                           cservername, file_name);
5326         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5327         r->file_type    = file_type;
5328         r->file_version = file_version;
5329
5330         return WERR_OK;
5331 }
5332
5333 /********************************************************************
5334  ********************************************************************/
5335
5336 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5337                                                  const struct spoolss_DriverInfo8 *driver,
5338                                                  const char *cservername,
5339                                                  struct spoolss_DriverFileInfo **info_p,
5340                                                  uint32_t *count_p)
5341 {
5342         struct spoolss_DriverFileInfo *info = NULL;
5343         uint32_t count = 0;
5344         WERROR result;
5345         uint32_t i;
5346
5347         *info_p = NULL;
5348         *count_p = 0;
5349
5350         if (strlen(driver->driver_path)) {
5351                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5352                                             struct spoolss_DriverFileInfo,
5353                                             count + 1);
5354                 W_ERROR_HAVE_NO_MEMORY(info);
5355                 result = fill_spoolss_DriverFileInfo(info,
5356                                                      &info[count],
5357                                                      cservername,
5358                                                      driver->driver_path,
5359                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5360                                                      0);
5361                 W_ERROR_NOT_OK_RETURN(result);
5362                 count++;
5363         }
5364
5365         if (strlen(driver->config_file)) {
5366                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5367                                             struct spoolss_DriverFileInfo,
5368                                             count + 1);
5369                 W_ERROR_HAVE_NO_MEMORY(info);
5370                 result = fill_spoolss_DriverFileInfo(info,
5371                                                      &info[count],
5372                                                      cservername,
5373                                                      driver->config_file,
5374                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5375                                                      0);
5376                 W_ERROR_NOT_OK_RETURN(result);
5377                 count++;
5378         }
5379
5380         if (strlen(driver->data_file)) {
5381                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5382                                             struct spoolss_DriverFileInfo,
5383                                             count + 1);
5384                 W_ERROR_HAVE_NO_MEMORY(info);
5385                 result = fill_spoolss_DriverFileInfo(info,
5386                                                      &info[count],
5387                                                      cservername,
5388                                                      driver->data_file,
5389                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5390                                                      0);
5391                 W_ERROR_NOT_OK_RETURN(result);
5392                 count++;
5393         }
5394
5395         if (strlen(driver->help_file)) {
5396                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5397                                             struct spoolss_DriverFileInfo,
5398                                             count + 1);
5399                 W_ERROR_HAVE_NO_MEMORY(info);
5400                 result = fill_spoolss_DriverFileInfo(info,
5401                                                      &info[count],
5402                                                      cservername,
5403                                                      driver->help_file,
5404                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5405                                                      0);
5406                 W_ERROR_NOT_OK_RETURN(result);
5407                 count++;
5408         }
5409
5410         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5411                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5412                                             struct spoolss_DriverFileInfo,
5413                                             count + 1);
5414                 W_ERROR_HAVE_NO_MEMORY(info);
5415                 result = fill_spoolss_DriverFileInfo(info,
5416                                                      &info[count],
5417                                                      cservername,
5418                                                      driver->dependent_files[i],
5419                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5420                                                      0);
5421                 W_ERROR_NOT_OK_RETURN(result);
5422                 count++;
5423         }
5424
5425         *info_p = info;
5426         *count_p = count;
5427
5428         return WERR_OK;
5429 }
5430
5431 /********************************************************************
5432  * fill a spoolss_DriverInfo101 struct
5433  ********************************************************************/
5434
5435 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5436                                           struct spoolss_DriverInfo101 *r,
5437                                           const struct spoolss_DriverInfo8 *driver,
5438                                           const char *servername)
5439 {
5440         const char *cservername = canon_servername(servername);
5441         WERROR result;
5442
5443         r->version              = driver->version;
5444
5445         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5446         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5447         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5448         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5449
5450         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5451                                                     cservername,
5452                                                     &r->file_info,
5453                                                     &r->file_count);
5454         if (!W_ERROR_IS_OK(result)) {
5455                 return result;
5456         }
5457
5458         FILL_DRIVER_STRING(mem_ctx,
5459                            driver->monitor_name,
5460                            r->monitor_name);
5461
5462         FILL_DRIVER_STRING(mem_ctx,
5463                            driver->default_datatype,
5464                            r->default_datatype);
5465
5466         result = string_array_from_driver_info(mem_ctx,
5467                                                driver->previous_names,
5468                                                &r->previous_names,
5469                                                NULL, NULL, 0);
5470         if (!W_ERROR_IS_OK(result)) {
5471                 return result;
5472         }
5473
5474         r->driver_date          = driver->driver_date;
5475         r->driver_version       = driver->driver_version;
5476
5477         FILL_DRIVER_STRING(mem_ctx,
5478                            driver->manufacturer_name,
5479                            r->manufacturer_name);
5480         FILL_DRIVER_STRING(mem_ctx,
5481                            driver->manufacturer_url,
5482                            r->manufacturer_url);
5483         FILL_DRIVER_STRING(mem_ctx,
5484                            driver->hardware_id,
5485                            r->hardware_id);
5486         FILL_DRIVER_STRING(mem_ctx,
5487                            driver->provider,
5488                            r->provider);
5489
5490         return WERR_OK;
5491 }
5492 #endif
5493 /********************************************************************
5494  ********************************************************************/
5495
5496 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5497                                                   const struct auth_serversupplied_info *session_info,
5498                                                   struct messaging_context *msg_ctx,
5499                                                   uint32_t level,
5500                                                   union spoolss_DriverInfo *r,
5501                                                   int snum,
5502                                                   const char *servername,
5503                                                   const char *architecture,
5504                                                   uint32_t version)
5505 {
5506         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5507         struct spoolss_DriverInfo8 *driver;
5508         WERROR result;
5509
5510         if (level == 101) {
5511                 return WERR_UNKNOWN_LEVEL;
5512         }
5513
5514         result = winreg_get_printer(mem_ctx,
5515                                     session_info,
5516                                     msg_ctx,
5517                                     lp_const_servicename(snum),
5518                                     &pinfo2);
5519
5520         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5521                 win_errstr(result)));
5522
5523         if (!W_ERROR_IS_OK(result)) {
5524                 return WERR_INVALID_PRINTER_NAME;
5525         }
5526
5527         result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5528                                    architecture,
5529                                    pinfo2->drivername, version, &driver);
5530
5531         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5532                 win_errstr(result)));
5533
5534         if (!W_ERROR_IS_OK(result)) {
5535                 /*
5536                  * Is this a W2k client ?
5537                  */
5538
5539                 if (version < 3) {
5540                         talloc_free(pinfo2);
5541                         return WERR_UNKNOWN_PRINTER_DRIVER;
5542                 }
5543
5544                 /* Yes - try again with a WinNT driver. */
5545                 version = 2;
5546                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5547                                            architecture,
5548                                            pinfo2->drivername,
5549                                            version, &driver);
5550                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5551                         win_errstr(result)));
5552                 if (!W_ERROR_IS_OK(result)) {
5553                         talloc_free(pinfo2);
5554                         return WERR_UNKNOWN_PRINTER_DRIVER;
5555                 }
5556         }
5557
5558         switch (level) {
5559         case 1:
5560                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5561                 break;
5562         case 2:
5563                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5564                 break;
5565         case 3:
5566                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5567                 break;
5568         case 4:
5569                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5570                 break;
5571         case 5:
5572                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5573                 break;
5574         case 6:
5575                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5576                 break;
5577         case 8:
5578                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5579                 break;
5580 #if 0 /* disabled until marshalling issues are resolved - gd */
5581         case 101:
5582                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5583                 break;
5584 #endif
5585         default:
5586                 result = WERR_UNKNOWN_LEVEL;
5587                 break;
5588         }
5589
5590         talloc_free(pinfo2);
5591         talloc_free(driver);
5592
5593         return result;
5594 }
5595
5596 /****************************************************************
5597  _spoolss_GetPrinterDriver2
5598 ****************************************************************/
5599
5600 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5601                                   struct spoolss_GetPrinterDriver2 *r)
5602 {
5603         struct printer_handle *printer;
5604         WERROR result;
5605
5606         int snum;
5607
5608         /* that's an [in out] buffer */
5609
5610         if (!r->in.buffer && (r->in.offered != 0)) {
5611                 return WERR_INVALID_PARAM;
5612         }
5613
5614         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5615
5616         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5617                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5618                 return WERR_INVALID_PRINTER_NAME;
5619         }
5620
5621         *r->out.needed = 0;
5622         *r->out.server_major_version = 0;
5623         *r->out.server_minor_version = 0;
5624
5625         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5626                 return WERR_BADFID;
5627         }
5628
5629         result = construct_printer_driver_info_level(p->mem_ctx,
5630                                                      get_session_info_system(),
5631                                                      p->msg_ctx,
5632                                                      r->in.level, r->out.info,
5633                                                      snum, printer->servername,
5634                                                      r->in.architecture,
5635                                                      r->in.client_major_version);
5636         if (!W_ERROR_IS_OK(result)) {
5637                 TALLOC_FREE(r->out.info);
5638                 return result;
5639         }
5640
5641         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5642                                                r->out.info, r->in.level);
5643         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5644
5645         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5646 }
5647
5648
5649 /****************************************************************
5650  _spoolss_StartPagePrinter
5651 ****************************************************************/
5652
5653 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5654                                  struct spoolss_StartPagePrinter *r)
5655 {
5656         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5657
5658         if (!Printer) {
5659                 DEBUG(3,("_spoolss_StartPagePrinter: "
5660                         "Error in startpageprinter printer handle\n"));
5661                 return WERR_BADFID;
5662         }
5663
5664         Printer->page_started = true;
5665         return WERR_OK;
5666 }
5667
5668 /****************************************************************
5669  _spoolss_EndPagePrinter
5670 ****************************************************************/
5671
5672 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5673                                struct spoolss_EndPagePrinter *r)
5674 {
5675         int snum;
5676
5677         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5678
5679         if (!Printer) {
5680                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5681                         OUR_HANDLE(r->in.handle)));
5682                 return WERR_BADFID;
5683         }
5684
5685         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5686                 return WERR_BADFID;
5687
5688         Printer->page_started = false;
5689         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5690
5691         return WERR_OK;
5692 }
5693
5694 /****************************************************************
5695  _spoolss_StartDocPrinter
5696 ****************************************************************/
5697
5698 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5699                                 struct spoolss_StartDocPrinter *r)
5700 {
5701         struct spoolss_DocumentInfo1 *info_1;
5702         int snum;
5703         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5704         WERROR werr;
5705
5706         if (!Printer) {
5707                 DEBUG(2,("_spoolss_StartDocPrinter: "
5708                         "Invalid handle (%s:%u:%u)\n",
5709                         OUR_HANDLE(r->in.handle)));
5710                 return WERR_BADFID;
5711         }
5712
5713         if (Printer->jobid) {
5714                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5715                           "StartDocPrinter called twice! "
5716                           "(existing jobid = %d)\n", Printer->jobid));
5717                 return WERR_INVALID_HANDLE;
5718         }
5719
5720         if (r->in.level != 1) {
5721                 return WERR_UNKNOWN_LEVEL;
5722         }
5723
5724         info_1 = r->in.info.info1;
5725
5726         /*
5727          * a nice thing with NT is it doesn't listen to what you tell it.
5728          * when asked to send _only_ RAW datas, it tries to send datas
5729          * in EMF format.
5730          *
5731          * So I add checks like in NT Server ...
5732          */
5733
5734         if (info_1->datatype) {
5735                 if (strcmp(info_1->datatype, "RAW") != 0) {
5736                         *r->out.job_id = 0;
5737                         return WERR_INVALID_DATATYPE;
5738                 }
5739         }
5740
5741         /* get the share number of the printer */
5742         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5743                 return WERR_BADFID;
5744         }
5745
5746         werr = print_job_start(p->session_info,
5747                                p->msg_ctx,
5748                                p->client_id->name,
5749                                snum,
5750                                info_1->document_name,
5751                                info_1->output_file,
5752                                Printer->devmode,
5753                                &Printer->jobid);
5754
5755         /* An error occured in print_job_start() so return an appropriate
5756            NT error code. */
5757
5758         if (!W_ERROR_IS_OK(werr)) {
5759                 return werr;
5760         }
5761
5762         Printer->document_started = true;
5763         *r->out.job_id = Printer->jobid;
5764
5765         return WERR_OK;
5766 }
5767
5768 /****************************************************************
5769  _spoolss_EndDocPrinter
5770 ****************************************************************/
5771
5772 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5773                               struct spoolss_EndDocPrinter *r)
5774 {
5775         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5776         NTSTATUS status;
5777         int snum;
5778
5779         if (!Printer) {
5780                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5781                         OUR_HANDLE(r->in.handle)));
5782                 return WERR_BADFID;
5783         }
5784
5785         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5786                 return WERR_BADFID;
5787         }
5788
5789         Printer->document_started = false;
5790         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5791         if (!NT_STATUS_IS_OK(status)) {
5792                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5793                           "print_job_end failed [%s]\n",
5794                           nt_errstr(status)));
5795         }
5796
5797         Printer->jobid = 0;
5798         return ntstatus_to_werror(status);
5799 }
5800
5801 /****************************************************************
5802  _spoolss_WritePrinter
5803 ****************************************************************/
5804
5805 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5806                              struct spoolss_WritePrinter *r)
5807 {
5808         ssize_t buffer_written;
5809         int snum;
5810         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5811
5812         if (!Printer) {
5813                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5814                         OUR_HANDLE(r->in.handle)));
5815                 *r->out.num_written = r->in._data_size;
5816                 return WERR_BADFID;
5817         }
5818
5819         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5820                 return WERR_BADFID;
5821
5822         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5823         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5824                                                    snum, Printer->jobid,
5825                                                    (const char *)r->in.data.data,
5826                                                    (size_t)r->in._data_size);
5827         if (buffer_written == (ssize_t)-1) {
5828                 *r->out.num_written = 0;
5829                 if (errno == ENOSPC)
5830                         return WERR_NO_SPOOL_SPACE;
5831                 else
5832                         return WERR_ACCESS_DENIED;
5833         }
5834
5835         *r->out.num_written = r->in._data_size;
5836
5837         return WERR_OK;
5838 }
5839
5840 /********************************************************************
5841  * api_spoolss_getprinter
5842  * called from the spoolss dispatcher
5843  *
5844  ********************************************************************/
5845
5846 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5847                               struct pipes_struct *p)
5848 {
5849         const struct auth_serversupplied_info *session_info = p->session_info;
5850         int snum;
5851         WERROR errcode = WERR_BADFUNC;
5852         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5853
5854         if (!Printer) {
5855                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5856                         OUR_HANDLE(handle)));
5857                 return WERR_BADFID;
5858         }
5859
5860         if (!get_printer_snum(p, handle, &snum, NULL))
5861                 return WERR_BADFID;
5862
5863         switch (command) {
5864         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5865                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5866                 break;
5867         case SPOOLSS_PRINTER_CONTROL_RESUME:
5868         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5869                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5870                 break;
5871         case SPOOLSS_PRINTER_CONTROL_PURGE:
5872                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5873                 break;
5874         default:
5875                 return WERR_UNKNOWN_LEVEL;
5876         }
5877
5878         return errcode;
5879 }
5880
5881
5882 /****************************************************************
5883  _spoolss_AbortPrinter
5884  * From MSDN: "Deletes printer's spool file if printer is configured
5885  * for spooling"
5886 ****************************************************************/
5887
5888 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5889                              struct spoolss_AbortPrinter *r)
5890 {
5891         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5892         int             snum;
5893         WERROR          errcode = WERR_OK;
5894
5895         if (!Printer) {
5896                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5897                         OUR_HANDLE(r->in.handle)));
5898                 return WERR_BADFID;
5899         }
5900
5901         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5902                 return WERR_BADFID;
5903
5904         if (!Printer->document_started) {
5905                 return WERR_SPL_NO_STARTDOC;
5906         }
5907
5908         errcode = print_job_delete(p->session_info,
5909                                    p->msg_ctx,
5910                                    snum,
5911                                    Printer->jobid);
5912
5913         return errcode;
5914 }
5915
5916 /********************************************************************
5917  * called by spoolss_api_setprinter
5918  * when updating a printer description
5919  ********************************************************************/
5920
5921 static WERROR update_printer_sec(struct policy_handle *handle,
5922                                  struct pipes_struct *p,
5923                                  struct sec_desc_buf *secdesc_ctr)
5924 {
5925         struct spoolss_security_descriptor *new_secdesc = NULL;
5926         struct spoolss_security_descriptor *old_secdesc = NULL;
5927         const char *printer;
5928         WERROR result;
5929         int snum;
5930
5931         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5932
5933         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5934                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5935                          OUR_HANDLE(handle)));
5936
5937                 result = WERR_BADFID;
5938                 goto done;
5939         }
5940
5941         if (secdesc_ctr == NULL) {
5942                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5943                 result = WERR_INVALID_PARAM;
5944                 goto done;
5945         }
5946         printer = lp_const_servicename(snum);
5947
5948         /* Check the user has permissions to change the security
5949            descriptor.  By experimentation with two NT machines, the user
5950            requires Full Access to the printer to change security
5951            information. */
5952
5953         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5954                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5955                 result = WERR_ACCESS_DENIED;
5956                 goto done;
5957         }
5958
5959         /* NT seems to like setting the security descriptor even though
5960            nothing may have actually changed. */
5961         result = winreg_get_printer_secdesc(p->mem_ctx,
5962                                             get_session_info_system(),
5963                                             p->msg_ctx,
5964                                             printer,
5965                                             &old_secdesc);
5966         if (!W_ERROR_IS_OK(result)) {
5967                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5968                 result = WERR_BADFID;
5969                 goto done;
5970         }
5971
5972         if (DEBUGLEVEL >= 10) {
5973                 struct security_acl *the_acl;
5974                 int i;
5975
5976                 the_acl = old_secdesc->dacl;
5977                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5978                            printer, the_acl->num_aces));
5979
5980                 for (i = 0; i < the_acl->num_aces; i++) {
5981                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5982                                            &the_acl->aces[i].trustee),
5983                                   the_acl->aces[i].access_mask));
5984                 }
5985
5986                 the_acl = secdesc_ctr->sd->dacl;
5987
5988                 if (the_acl) {
5989                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5990                                    printer, the_acl->num_aces));
5991
5992                         for (i = 0; i < the_acl->num_aces; i++) {
5993                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5994                                                    &the_acl->aces[i].trustee),
5995                                            the_acl->aces[i].access_mask));
5996                         }
5997                 } else {
5998                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5999                 }
6000         }
6001
6002         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
6003         if (new_secdesc == NULL) {
6004                 result = WERR_NOMEM;
6005                 goto done;
6006         }
6007
6008         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6009                 result = WERR_OK;
6010                 goto done;
6011         }
6012
6013         result = winreg_set_printer_secdesc(p->mem_ctx,
6014                                             get_session_info_system(),
6015                                             p->msg_ctx,
6016                                             printer,
6017                                             new_secdesc);
6018
6019  done:
6020         return result;
6021 }
6022
6023 /********************************************************************
6024  Canonicalize printer info from a client
6025  ********************************************************************/
6026
6027 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6028                              struct spoolss_SetPrinterInfo2 *info2,
6029                              int snum)
6030 {
6031         fstring printername;
6032         const char *p;
6033
6034         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6035                 "portname=%s drivername=%s comment=%s location=%s\n",
6036                 info2->servername, info2->printername, info2->sharename,
6037                 info2->portname, info2->drivername, info2->comment,
6038                 info2->location));
6039
6040         /* we force some elements to "correct" values */
6041         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6042         if (info2->servername == NULL) {
6043                 return false;
6044         }
6045         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6046         if (info2->sharename == NULL) {
6047                 return false;
6048         }
6049
6050         /* check to see if we allow printername != sharename */
6051         if (lp_force_printername(snum)) {
6052                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6053                                         global_myname(), info2->sharename);
6054         } else {
6055                 /* make sure printername is in \\server\printername format */
6056                 fstrcpy(printername, info2->printername);
6057                 p = printername;
6058                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6059                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6060                                 p++;
6061                 }
6062
6063                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6064                                         global_myname(), p);
6065         }
6066         if (info2->printername == NULL) {
6067                 return false;
6068         }
6069
6070         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6071         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6072
6073         return true;
6074 }
6075
6076 /****************************************************************************
6077 ****************************************************************************/
6078
6079 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6080 {
6081         char *cmd = lp_addport_cmd();
6082         char *command = NULL;
6083         int ret;
6084         bool is_print_op = false;
6085
6086         if ( !*cmd ) {
6087                 return WERR_ACCESS_DENIED;
6088         }
6089
6090         command = talloc_asprintf(ctx,
6091                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6092         if (!command) {
6093                 return WERR_NOMEM;
6094         }
6095
6096         if ( token )
6097                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6098
6099         DEBUG(10,("Running [%s]\n", command));
6100
6101         /********* BEGIN SePrintOperatorPrivilege **********/
6102
6103         if ( is_print_op )
6104                 become_root();
6105
6106         ret = smbrun(command, NULL);
6107
6108         if ( is_print_op )
6109                 unbecome_root();
6110
6111         /********* END SePrintOperatorPrivilege **********/
6112
6113         DEBUGADD(10,("returned [%d]\n", ret));
6114
6115         TALLOC_FREE(command);
6116
6117         if ( ret != 0 ) {
6118                 return WERR_ACCESS_DENIED;
6119         }
6120
6121         return WERR_OK;
6122 }
6123
6124 /****************************************************************************
6125 ****************************************************************************/
6126
6127 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6128                              struct spoolss_SetPrinterInfo2 *info2,
6129                              const char *remote_machine,
6130                              struct messaging_context *msg_ctx)
6131 {
6132         char *cmd = lp_addprinter_cmd();
6133         char **qlines;
6134         char *command = NULL;
6135         int numlines;
6136         int ret;
6137         int fd;
6138         bool is_print_op = false;
6139
6140         if (!remote_machine) {
6141                 return false;
6142         }
6143
6144         command = talloc_asprintf(ctx,
6145                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6146                         cmd, info2->printername, info2->sharename,
6147                         info2->portname, info2->drivername,
6148                         info2->location, info2->comment, remote_machine);
6149         if (!command) {
6150                 return false;
6151         }
6152
6153         if ( token )
6154                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6155
6156         DEBUG(10,("Running [%s]\n", command));
6157
6158         /********* BEGIN SePrintOperatorPrivilege **********/
6159
6160         if ( is_print_op )
6161                 become_root();
6162
6163         if ( (ret = smbrun(command, &fd)) == 0 ) {
6164                 /* Tell everyone we updated smb.conf. */
6165                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6166         }
6167
6168         if ( is_print_op )
6169                 unbecome_root();
6170
6171         /********* END SePrintOperatorPrivilege **********/
6172
6173         DEBUGADD(10,("returned [%d]\n", ret));
6174
6175         TALLOC_FREE(command);
6176
6177         if ( ret != 0 ) {
6178                 if (fd != -1)
6179                         close(fd);
6180                 return false;
6181         }
6182
6183         /* reload our services immediately */
6184         become_root();
6185         reload_services(msg_ctx, -1, false);
6186         unbecome_root();
6187
6188         numlines = 0;
6189         /* Get lines and convert them back to dos-codepage */
6190         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6191         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6192         close(fd);
6193
6194         /* Set the portname to what the script says the portname should be. */
6195         /* but don't require anything to be return from the script exit a good error code */
6196
6197         if (numlines) {
6198                 /* Set the portname to what the script says the portname should be. */
6199                 info2->portname = talloc_strdup(ctx, qlines[0]);
6200                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6201         }
6202
6203         TALLOC_FREE(qlines);
6204         return true;
6205 }
6206
6207 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6208                                const struct auth_serversupplied_info *session_info,
6209                                struct messaging_context *msg_ctx,
6210                                int snum,
6211                                struct spoolss_SetPrinterInfo2 *printer,
6212                                struct spoolss_PrinterInfo2 *old_printer)
6213 {
6214         bool force_update = (old_printer == NULL);
6215         const char *dnsdomname;
6216         const char *longname;
6217         const char *uncname;
6218         const char *spooling;
6219         DATA_BLOB buffer;
6220         WERROR result = WERR_OK;
6221
6222         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6223                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6224                 winreg_set_printer_dataex(mem_ctx,
6225                                           session_info,
6226                                           msg_ctx,
6227                                           printer->sharename,
6228                                           SPOOL_DSSPOOLER_KEY,
6229                                           SPOOL_REG_DRIVERNAME,
6230                                           REG_SZ,
6231                                           buffer.data,
6232                                           buffer.length);
6233
6234                 if (!force_update) {
6235                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6236                                 printer->drivername));
6237
6238                         notify_printer_driver(server_event_context(), msg_ctx,
6239                                               snum, printer->drivername ?
6240                                               printer->drivername : "");
6241                 }
6242         }
6243
6244         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6245                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6246                 winreg_set_printer_dataex(mem_ctx,
6247                                           session_info,
6248                                           msg_ctx,
6249                                           printer->sharename,
6250                                           SPOOL_DSSPOOLER_KEY,
6251                                           SPOOL_REG_DESCRIPTION,
6252                                           REG_SZ,
6253                                           buffer.data,
6254                                           buffer.length);
6255
6256                 if (!force_update) {
6257                         notify_printer_comment(server_event_context(), msg_ctx,
6258                                                snum, printer->comment ?
6259                                                printer->comment : "");
6260                 }
6261         }
6262
6263         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6264                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6265                 winreg_set_printer_dataex(mem_ctx,
6266                                           session_info,
6267                                           msg_ctx,
6268                                           printer->sharename,
6269                                           SPOOL_DSSPOOLER_KEY,
6270                                           SPOOL_REG_PRINTSHARENAME,
6271                                           REG_SZ,
6272                                           buffer.data,
6273                                           buffer.length);
6274
6275                 if (!force_update) {
6276                         notify_printer_sharename(server_event_context(),
6277                                                  msg_ctx,
6278                                                  snum, printer->sharename ?
6279                                                  printer->sharename : "");
6280                 }
6281         }
6282
6283         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6284                 const char *p;
6285
6286                 p = strrchr(printer->printername, '\\' );
6287                 if (p != NULL) {
6288                         p++;
6289                 } else {
6290                         p = printer->printername;
6291                 }
6292
6293                 push_reg_sz(mem_ctx, &buffer, p);
6294                 winreg_set_printer_dataex(mem_ctx,
6295                                           session_info,
6296                                           msg_ctx,
6297                                           printer->sharename,
6298                                           SPOOL_DSSPOOLER_KEY,
6299                                           SPOOL_REG_PRINTERNAME,
6300                                           REG_SZ,
6301                                           buffer.data,
6302                                           buffer.length);
6303
6304                 if (!force_update) {
6305                         notify_printer_printername(server_event_context(),
6306                                                    msg_ctx, snum, p ? p : "");
6307                 }
6308         }
6309
6310         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6311                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6312                 winreg_set_printer_dataex(mem_ctx,
6313                                           session_info,
6314                                           msg_ctx,
6315                                           printer->sharename,
6316                                           SPOOL_DSSPOOLER_KEY,
6317                                           SPOOL_REG_PORTNAME,
6318                                           REG_SZ,
6319                                           buffer.data,
6320                                           buffer.length);
6321
6322                 if (!force_update) {
6323                         notify_printer_port(server_event_context(),
6324                                             msg_ctx, snum, printer->portname ?
6325                                             printer->portname : "");
6326                 }
6327         }
6328
6329         if (force_update || !strequal(printer->location, old_printer->location)) {
6330                 push_reg_sz(mem_ctx, &buffer, printer->location);
6331                 winreg_set_printer_dataex(mem_ctx,
6332                                           session_info,
6333                                           msg_ctx,
6334                                           printer->sharename,
6335                                           SPOOL_DSSPOOLER_KEY,
6336                                           SPOOL_REG_LOCATION,
6337                                           REG_SZ,
6338                                           buffer.data,
6339                                           buffer.length);
6340
6341                 if (!force_update) {
6342                         notify_printer_location(server_event_context(),
6343                                                 msg_ctx, snum,
6344                                                 printer->location ?
6345                                                 printer->location : "");
6346                 }
6347         }
6348
6349         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6350                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6351                 winreg_set_printer_dataex(mem_ctx,
6352                                           session_info,
6353                                           msg_ctx,
6354                                           printer->sharename,
6355                                           SPOOL_DSSPOOLER_KEY,
6356                                           SPOOL_REG_PRINTSEPARATORFILE,
6357                                           REG_SZ,
6358                                           buffer.data,
6359                                           buffer.length);
6360
6361                 if (!force_update) {
6362                         notify_printer_sepfile(server_event_context(),
6363                                                msg_ctx, snum,
6364                                                printer->sepfile ?
6365                                                printer->sepfile : "");
6366                 }
6367         }
6368
6369         if (force_update || printer->starttime != old_printer->starttime) {
6370                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6371                 SIVAL(buffer.data, 0, printer->starttime);
6372                 winreg_set_printer_dataex(mem_ctx,
6373                                           session_info,
6374                                           msg_ctx,
6375                                           printer->sharename,
6376                                           SPOOL_DSSPOOLER_KEY,
6377                                           SPOOL_REG_PRINTSTARTTIME,
6378                                           REG_DWORD,
6379                                           buffer.data,
6380                                           buffer.length);
6381         }
6382
6383         if (force_update || printer->untiltime != old_printer->untiltime) {
6384                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6385                 SIVAL(buffer.data, 0, printer->untiltime);
6386                 winreg_set_printer_dataex(mem_ctx,
6387                                           session_info,
6388                                           msg_ctx,
6389                                           printer->sharename,
6390                                           SPOOL_DSSPOOLER_KEY,
6391                                           SPOOL_REG_PRINTENDTIME,
6392                                           REG_DWORD,
6393                                           buffer.data,
6394                                           buffer.length);
6395         }
6396
6397         if (force_update || printer->priority != old_printer->priority) {
6398                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6399                 SIVAL(buffer.data, 0, printer->priority);
6400                 winreg_set_printer_dataex(mem_ctx,
6401                                           session_info,
6402                                           msg_ctx,
6403                                           printer->sharename,
6404                                           SPOOL_DSSPOOLER_KEY,
6405                                           SPOOL_REG_PRIORITY,
6406                                           REG_DWORD,
6407                                           buffer.data,
6408                                           buffer.length);
6409         }
6410
6411         if (force_update || printer->attributes != old_printer->attributes) {
6412                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6413                 SIVAL(buffer.data, 0, (printer->attributes &
6414                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6415                 winreg_set_printer_dataex(mem_ctx,
6416                                           session_info,
6417                                           msg_ctx,
6418                                           printer->sharename,
6419                                           SPOOL_DSSPOOLER_KEY,
6420                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6421                                           REG_DWORD,
6422                                           buffer.data,
6423                                           buffer.length);
6424
6425                 switch (printer->attributes & 0x3) {
6426                         case 0:
6427                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6428                                 break;
6429                         case 1:
6430                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6431                                 break;
6432                         case 2:
6433                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6434                                 break;
6435                         default:
6436                                 spooling = "unknown";
6437                 }
6438                 push_reg_sz(mem_ctx, &buffer, spooling);
6439                 winreg_set_printer_dataex(mem_ctx,
6440                                           session_info,
6441                                           msg_ctx,
6442                                           printer->sharename,
6443                                           SPOOL_DSSPOOLER_KEY,
6444                                           SPOOL_REG_PRINTSPOOLING,
6445                                           REG_SZ,
6446                                           buffer.data,
6447                                           buffer.length);
6448         }
6449
6450         push_reg_sz(mem_ctx, &buffer, global_myname());
6451         winreg_set_printer_dataex(mem_ctx,
6452                                   session_info,
6453                                   msg_ctx,
6454                                   printer->sharename,
6455                                   SPOOL_DSSPOOLER_KEY,
6456                                   SPOOL_REG_SHORTSERVERNAME,
6457                                   REG_SZ,
6458                                   buffer.data,
6459                                   buffer.length);
6460
6461         dnsdomname = get_mydnsfullname();
6462         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6463                 longname = talloc_strdup(mem_ctx, dnsdomname);
6464         } else {
6465                 longname = talloc_strdup(mem_ctx, global_myname());
6466         }
6467         if (longname == NULL) {
6468                 result = WERR_NOMEM;
6469                 goto done;
6470         }
6471
6472         push_reg_sz(mem_ctx, &buffer, longname);
6473         winreg_set_printer_dataex(mem_ctx,
6474                                   session_info,
6475                                   msg_ctx,
6476                                   printer->sharename,
6477                                   SPOOL_DSSPOOLER_KEY,
6478                                   SPOOL_REG_SERVERNAME,
6479                                   REG_SZ,
6480                                   buffer.data,
6481                                   buffer.length);
6482
6483         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6484                                   global_myname(), printer->sharename);
6485         push_reg_sz(mem_ctx, &buffer, uncname);
6486         winreg_set_printer_dataex(mem_ctx,
6487                                   session_info,
6488                                   msg_ctx,
6489                                   printer->sharename,
6490                                   SPOOL_DSSPOOLER_KEY,
6491                                   SPOOL_REG_UNCNAME,
6492                                   REG_SZ,
6493                                   buffer.data,
6494                                   buffer.length);
6495
6496 done:
6497         return result;
6498 }
6499
6500 /********************************************************************
6501  * Called by spoolss_api_setprinter
6502  * when updating a printer description.
6503  ********************************************************************/
6504
6505 static WERROR update_printer(struct pipes_struct *p,
6506                              struct policy_handle *handle,
6507                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6508                              struct spoolss_DeviceMode *devmode)
6509 {
6510         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6511         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6512         struct spoolss_PrinterInfo2 *old_printer;
6513         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6514         int snum;
6515         WERROR result = WERR_OK;
6516         TALLOC_CTX *tmp_ctx;
6517
6518         DEBUG(8,("update_printer\n"));
6519
6520         tmp_ctx = talloc_new(p->mem_ctx);
6521         if (tmp_ctx == NULL) {
6522                 return WERR_NOMEM;
6523         }
6524
6525         if (!Printer) {
6526                 result = WERR_BADFID;
6527                 goto done;
6528         }
6529
6530         if (!get_printer_snum(p, handle, &snum, NULL)) {
6531                 result = WERR_BADFID;
6532                 goto done;
6533         }
6534
6535         result = winreg_get_printer(tmp_ctx,
6536                                     get_session_info_system(),
6537                                     p->msg_ctx,
6538                                     lp_const_servicename(snum),
6539                                     &old_printer);
6540         if (!W_ERROR_IS_OK(result)) {
6541                 result = WERR_BADFID;
6542                 goto done;
6543         }
6544
6545         /* Do sanity check on the requested changes for Samba */
6546         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6547                 result = WERR_INVALID_PARAM;
6548                 goto done;
6549         }
6550
6551         /* FIXME!!! If the driver has changed we really should verify that
6552            it is installed before doing much else   --jerry */
6553
6554         /* Check calling user has permission to update printer description */
6555         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6556                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6557                 result = WERR_ACCESS_DENIED;
6558                 goto done;
6559         }
6560
6561         /* Call addprinter hook */
6562         /* Check changes to see if this is really needed */
6563
6564         if (*lp_addprinter_cmd() &&
6565                         (!strequal(printer->drivername, old_printer->drivername) ||
6566                          !strequal(printer->comment, old_printer->comment) ||
6567                          !strequal(printer->portname, old_printer->portname) ||
6568                          !strequal(printer->location, old_printer->location)) )
6569         {
6570                 /* add_printer_hook() will call reload_services() */
6571                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6572                                       printer, p->client_id->addr,
6573                                       p->msg_ctx)) {
6574                         result = WERR_ACCESS_DENIED;
6575                         goto done;
6576                 }
6577         }
6578
6579         update_dsspooler(tmp_ctx,
6580                          get_session_info_system(),
6581                          p->msg_ctx,
6582                          snum,
6583                          printer,
6584                          old_printer);
6585
6586         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6587
6588         if (devmode == NULL) {
6589                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6590         }
6591         result = winreg_update_printer(tmp_ctx,
6592                                        get_session_info_system(),
6593                                        p->msg_ctx,
6594                                        printer->sharename,
6595                                        printer_mask,
6596                                        printer,
6597                                        devmode,
6598                                        NULL);
6599
6600 done:
6601         talloc_free(tmp_ctx);
6602
6603         return result;
6604 }
6605
6606 /****************************************************************************
6607 ****************************************************************************/
6608 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6609                                            struct policy_handle *handle,
6610                                            struct spoolss_SetPrinterInfo7 *info7)
6611 {
6612 #ifdef HAVE_ADS
6613         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6614         WERROR result;
6615         int snum;
6616         struct printer_handle *Printer;
6617
6618         if ( lp_security() != SEC_ADS ) {
6619                 return WERR_UNKNOWN_LEVEL;
6620         }
6621
6622         Printer = find_printer_index_by_hnd(p, handle);
6623
6624         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6625
6626         if (!Printer)
6627                 return WERR_BADFID;
6628
6629         if (!get_printer_snum(p, handle, &snum, NULL))
6630                 return WERR_BADFID;
6631
6632         result = winreg_get_printer(p->mem_ctx,
6633                                     get_session_info_system(),
6634                                     p->msg_ctx,
6635                                     lp_servicename(snum),
6636                                     &pinfo2);
6637         if (!W_ERROR_IS_OK(result)) {
6638                 return WERR_BADFID;
6639         }
6640
6641         nt_printer_publish(pinfo2,
6642                            get_session_info_system(),
6643                            p->msg_ctx,
6644                            pinfo2,
6645                            info7->action);
6646
6647         TALLOC_FREE(pinfo2);
6648         return WERR_OK;
6649 #else
6650         return WERR_UNKNOWN_LEVEL;
6651 #endif
6652 }
6653
6654 /********************************************************************
6655  ********************************************************************/
6656
6657 static WERROR update_printer_devmode(struct pipes_struct *p,
6658                                      struct policy_handle *handle,
6659                                      struct spoolss_DeviceMode *devmode)
6660 {
6661         int snum;
6662         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6663         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6664
6665         DEBUG(8,("update_printer_devmode\n"));
6666
6667         if (!Printer) {
6668                 return WERR_BADFID;
6669         }
6670
6671         if (!get_printer_snum(p, handle, &snum, NULL)) {
6672                 return WERR_BADFID;
6673         }
6674
6675         /* Check calling user has permission to update printer description */
6676         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6677                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6678                 return WERR_ACCESS_DENIED;
6679         }
6680
6681         return winreg_update_printer(p->mem_ctx,
6682                                      get_session_info_system(),
6683                                      p->msg_ctx,
6684                                      lp_const_servicename(snum),
6685                                      info2_mask,
6686                                      NULL,
6687                                      devmode,
6688                                      NULL);
6689 }
6690
6691
6692 /****************************************************************
6693  _spoolss_SetPrinter
6694 ****************************************************************/
6695
6696 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6697                            struct spoolss_SetPrinter *r)
6698 {
6699         WERROR result;
6700
6701         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6702
6703         if (!Printer) {
6704                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6705                         OUR_HANDLE(r->in.handle)));
6706                 return WERR_BADFID;
6707         }
6708
6709         /* check the level */
6710         switch (r->in.info_ctr->level) {
6711                 case 0:
6712                         return control_printer(r->in.handle, r->in.command, p);
6713                 case 2:
6714                         result = update_printer(p, r->in.handle,
6715                                                 r->in.info_ctr,
6716                                                 r->in.devmode_ctr->devmode);
6717                         if (!W_ERROR_IS_OK(result))
6718                                 return result;
6719                         if (r->in.secdesc_ctr->sd)
6720                                 result = update_printer_sec(r->in.handle, p,
6721                                                             r->in.secdesc_ctr);
6722                         return result;
6723                 case 3:
6724                         return update_printer_sec(r->in.handle, p,
6725                                                   r->in.secdesc_ctr);
6726                 case 7:
6727                         return publish_or_unpublish_printer(p, r->in.handle,
6728                                                             r->in.info_ctr->info.info7);
6729                 case 8:
6730                         return update_printer_devmode(p, r->in.handle,
6731                                                       r->in.devmode_ctr->devmode);
6732                 default:
6733                         return WERR_UNKNOWN_LEVEL;
6734         }
6735 }
6736
6737 /****************************************************************
6738  _spoolss_FindClosePrinterNotify
6739 ****************************************************************/
6740
6741 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6742                                        struct spoolss_FindClosePrinterNotify *r)
6743 {
6744         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6745
6746         if (!Printer) {
6747                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6748                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6749                 return WERR_BADFID;
6750         }
6751
6752         if (Printer->notify.cli_chan != NULL &&
6753             Printer->notify.cli_chan->active_connections > 0) {
6754                 int snum = -1;
6755
6756                 if (Printer->printer_type == SPLHND_PRINTER) {
6757                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6758                                 return WERR_BADFID;
6759                         }
6760                 }
6761
6762                 srv_spoolss_replycloseprinter(snum, Printer);
6763         }
6764
6765         Printer->notify.flags=0;
6766         Printer->notify.options=0;
6767         Printer->notify.localmachine[0]='\0';
6768         Printer->notify.printerlocal=0;
6769         TALLOC_FREE(Printer->notify.option);
6770
6771         return WERR_OK;
6772 }
6773
6774 /****************************************************************
6775  _spoolss_AddJob
6776 ****************************************************************/
6777
6778 WERROR _spoolss_AddJob(struct pipes_struct *p,
6779                        struct spoolss_AddJob *r)
6780 {
6781         if (!r->in.buffer && (r->in.offered != 0)) {
6782                 return WERR_INVALID_PARAM;
6783         }
6784
6785         /* this is what a NT server returns for AddJob. AddJob must fail on
6786          * non-local printers */
6787
6788         if (r->in.level != 1) {
6789                 return WERR_UNKNOWN_LEVEL;
6790         }
6791
6792         return WERR_INVALID_PARAM;
6793 }
6794
6795 /****************************************************************************
6796 fill_job_info1
6797 ****************************************************************************/
6798
6799 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6800                              struct spoolss_JobInfo1 *r,
6801                              const print_queue_struct *queue,
6802                              int position, int snum,
6803                              struct spoolss_PrinterInfo2 *pinfo2)
6804 {
6805         struct tm *t;
6806
6807         t = gmtime(&queue->time);
6808
6809         r->job_id               = queue->job;
6810
6811         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6812         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6813         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6814         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6815         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6816         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6817         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6818         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6819         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6820         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6821         r->text_status          = talloc_strdup(mem_ctx, "");
6822         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6823
6824         r->status               = nt_printj_status(queue->status);
6825         r->priority             = queue->priority;
6826         r->position             = position;
6827         r->total_pages          = queue->page_count;
6828         r->pages_printed        = 0; /* ??? */
6829
6830         init_systemtime(&r->submitted, t);
6831
6832         return WERR_OK;
6833 }
6834
6835 /****************************************************************************
6836 fill_job_info2
6837 ****************************************************************************/
6838
6839 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6840                              struct spoolss_JobInfo2 *r,
6841                              const print_queue_struct *queue,
6842                              int position, int snum,
6843                              struct spoolss_PrinterInfo2 *pinfo2,
6844                              struct spoolss_DeviceMode *devmode)
6845 {
6846         struct tm *t;
6847
6848         t = gmtime(&queue->time);
6849
6850         r->job_id               = queue->job;
6851
6852         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6853         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6854         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6855         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6856         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6857         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6858         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6859         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6860         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6861         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6862         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6863         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6864         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6865         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6866         r->parameters           = talloc_strdup(mem_ctx, "");
6867         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6868         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6869         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6870
6871         r->devmode              = devmode;
6872
6873         r->text_status          = talloc_strdup(mem_ctx, "");
6874         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6875
6876         r->secdesc              = NULL;
6877
6878         r->status               = nt_printj_status(queue->status);
6879         r->priority             = queue->priority;
6880         r->position             = position;
6881         r->start_time           = 0;
6882         r->until_time           = 0;
6883         r->total_pages          = queue->page_count;
6884         r->size                 = queue->size;
6885         init_systemtime(&r->submitted, t);
6886         r->time                 = 0;
6887         r->pages_printed        = 0; /* ??? */
6888
6889         return WERR_OK;
6890 }
6891
6892 /****************************************************************************
6893 fill_job_info3
6894 ****************************************************************************/
6895
6896 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6897                              struct spoolss_JobInfo3 *r,
6898                              const print_queue_struct *queue,
6899                              const print_queue_struct *next_queue,
6900                              int position, int snum,
6901                              struct spoolss_PrinterInfo2 *pinfo2)
6902 {
6903         r->job_id               = queue->job;
6904         r->next_job_id          = 0;
6905         if (next_queue) {
6906                 r->next_job_id  = next_queue->job;
6907         }
6908         r->reserved             = 0;
6909
6910         return WERR_OK;
6911 }
6912
6913 /****************************************************************************
6914  Enumjobs at level 1.
6915 ****************************************************************************/
6916
6917 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6918                               const print_queue_struct *queue,
6919                               uint32_t num_queues, int snum,
6920                               struct spoolss_PrinterInfo2 *pinfo2,
6921                               union spoolss_JobInfo **info_p,
6922                               uint32_t *count)
6923 {
6924         union spoolss_JobInfo *info;
6925         int i;
6926         WERROR result = WERR_OK;
6927
6928         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6929         W_ERROR_HAVE_NO_MEMORY(info);
6930
6931         *count = num_queues;
6932
6933         for (i=0; i<*count; i++) {
6934                 result = fill_job_info1(info,
6935                                         &info[i].info1,
6936                                         &queue[i],
6937                                         i,
6938                                         snum,
6939                                         pinfo2);
6940                 if (!W_ERROR_IS_OK(result)) {
6941                         goto out;
6942                 }
6943         }
6944
6945  out:
6946         if (!W_ERROR_IS_OK(result)) {
6947                 TALLOC_FREE(info);
6948                 *count = 0;
6949                 return result;
6950         }
6951
6952         *info_p = info;
6953
6954         return WERR_OK;
6955 }
6956
6957 /****************************************************************************
6958  Enumjobs at level 2.
6959 ****************************************************************************/
6960
6961 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6962                               const print_queue_struct *queue,
6963                               uint32_t num_queues, int snum,
6964                               struct spoolss_PrinterInfo2 *pinfo2,
6965                               union spoolss_JobInfo **info_p,
6966                               uint32_t *count)
6967 {
6968         union spoolss_JobInfo *info;
6969         int i;
6970         WERROR result = WERR_OK;
6971
6972         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6973         W_ERROR_HAVE_NO_MEMORY(info);
6974
6975         *count = num_queues;
6976
6977         for (i=0; i<*count; i++) {
6978                 struct spoolss_DeviceMode *devmode;
6979
6980                 result = spoolss_create_default_devmode(info,
6981                                                         pinfo2->printername,
6982                                                         &devmode);
6983                 if (!W_ERROR_IS_OK(result)) {
6984                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6985                         goto out;
6986                 }
6987
6988                 result = fill_job_info2(info,
6989                                         &info[i].info2,
6990                                         &queue[i],
6991                                         i,
6992                                         snum,
6993                                         pinfo2,
6994                                         devmode);
6995                 if (!W_ERROR_IS_OK(result)) {
6996                         goto out;
6997                 }
6998         }
6999
7000  out:
7001         if (!W_ERROR_IS_OK(result)) {
7002                 TALLOC_FREE(info);
7003                 *count = 0;
7004                 return result;
7005         }
7006
7007         *info_p = info;
7008
7009         return WERR_OK;
7010 }
7011
7012 /****************************************************************************
7013  Enumjobs at level 3.
7014 ****************************************************************************/
7015
7016 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7017                               const print_queue_struct *queue,
7018                               uint32_t num_queues, int snum,
7019                               struct spoolss_PrinterInfo2 *pinfo2,
7020                               union spoolss_JobInfo **info_p,
7021                               uint32_t *count)
7022 {
7023         union spoolss_JobInfo *info;
7024         int i;
7025         WERROR result = WERR_OK;
7026
7027         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
7028         W_ERROR_HAVE_NO_MEMORY(info);
7029
7030         *count = num_queues;
7031
7032         for (i=0; i<*count; i++) {
7033                 const print_queue_struct *next_queue = NULL;
7034
7035                 if (i+1 < *count) {
7036                         next_queue = &queue[i+1];
7037                 }
7038
7039                 result = fill_job_info3(info,
7040                                         &info[i].info3,
7041                                         &queue[i],
7042                                         next_queue,
7043                                         i,
7044                                         snum,
7045                                         pinfo2);
7046                 if (!W_ERROR_IS_OK(result)) {
7047                         goto out;
7048                 }
7049         }
7050
7051  out:
7052         if (!W_ERROR_IS_OK(result)) {
7053                 TALLOC_FREE(info);
7054                 *count = 0;
7055                 return result;
7056         }
7057
7058         *info_p = info;
7059
7060         return WERR_OK;
7061 }
7062
7063 /****************************************************************
7064  _spoolss_EnumJobs
7065 ****************************************************************/
7066
7067 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7068                          struct spoolss_EnumJobs *r)
7069 {
7070         WERROR result;
7071         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7072         int snum;
7073         print_status_struct prt_status;
7074         print_queue_struct *queue = NULL;
7075         uint32_t count;
7076
7077         /* that's an [in out] buffer */
7078
7079         if (!r->in.buffer && (r->in.offered != 0)) {
7080                 return WERR_INVALID_PARAM;
7081         }
7082
7083         DEBUG(4,("_spoolss_EnumJobs\n"));
7084
7085         *r->out.needed = 0;
7086         *r->out.count = 0;
7087         *r->out.info = NULL;
7088
7089         /* lookup the printer snum and tdb entry */
7090
7091         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7092                 return WERR_BADFID;
7093         }
7094
7095         result = winreg_get_printer(p->mem_ctx,
7096                                     get_session_info_system(),
7097                                     p->msg_ctx,
7098                                     lp_const_servicename(snum),
7099                                     &pinfo2);
7100         if (!W_ERROR_IS_OK(result)) {
7101                 return result;
7102         }
7103
7104         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7105         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7106                 count, prt_status.status, prt_status.message));
7107
7108         if (count == 0) {
7109                 SAFE_FREE(queue);
7110                 TALLOC_FREE(pinfo2);
7111                 return WERR_OK;
7112         }
7113
7114         switch (r->in.level) {
7115         case 1:
7116                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7117                                          pinfo2, r->out.info, r->out.count);
7118                 break;
7119         case 2:
7120                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7121                                          pinfo2, r->out.info, r->out.count);
7122                 break;
7123         case 3:
7124                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7125                                          pinfo2, r->out.info, r->out.count);
7126                 break;
7127         default:
7128                 result = WERR_UNKNOWN_LEVEL;
7129                 break;
7130         }
7131
7132         SAFE_FREE(queue);
7133         TALLOC_FREE(pinfo2);
7134
7135         if (!W_ERROR_IS_OK(result)) {
7136                 return result;
7137         }
7138
7139         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7140                                                      spoolss_EnumJobs,
7141                                                      *r->out.info, r->in.level,
7142                                                      *r->out.count);
7143         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7144         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7145
7146         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7147 }
7148
7149 /****************************************************************
7150  _spoolss_ScheduleJob
7151 ****************************************************************/
7152
7153 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7154                             struct spoolss_ScheduleJob *r)
7155 {
7156         return WERR_OK;
7157 }
7158
7159 /****************************************************************
7160 ****************************************************************/
7161
7162 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7163                                struct messaging_context *msg_ctx,
7164                                const char *printer_name,
7165                                uint32_t job_id,
7166                                struct spoolss_SetJobInfo1 *r)
7167 {
7168         char *old_doc_name;
7169
7170         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7171                 return WERR_BADFID;
7172         }
7173
7174         if (strequal(old_doc_name, r->document_name)) {
7175                 return WERR_OK;
7176         }
7177
7178         if (!print_job_set_name(server_event_context(), msg_ctx,
7179                                 printer_name, job_id, r->document_name)) {
7180                 return WERR_BADFID;
7181         }
7182
7183         return WERR_OK;
7184 }
7185
7186 /****************************************************************
7187  _spoolss_SetJob
7188 ****************************************************************/
7189
7190 WERROR _spoolss_SetJob(struct pipes_struct *p,
7191                        struct spoolss_SetJob *r)
7192 {
7193         const struct auth_serversupplied_info *session_info = p->session_info;
7194         int snum;
7195         WERROR errcode = WERR_BADFUNC;
7196
7197         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7198                 return WERR_BADFID;
7199         }
7200
7201         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7202                 return WERR_INVALID_PRINTER_NAME;
7203         }
7204
7205         switch (r->in.command) {
7206         case SPOOLSS_JOB_CONTROL_CANCEL:
7207         case SPOOLSS_JOB_CONTROL_DELETE:
7208                 errcode = print_job_delete(session_info, p->msg_ctx,
7209                                            snum, r->in.job_id);
7210                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7211                         errcode = WERR_OK;
7212                 }
7213                 break;
7214         case SPOOLSS_JOB_CONTROL_PAUSE:
7215                 if (print_job_pause(session_info, p->msg_ctx,
7216                                     snum, r->in.job_id, &errcode)) {
7217                         errcode = WERR_OK;
7218                 }
7219                 break;
7220         case SPOOLSS_JOB_CONTROL_RESTART:
7221         case SPOOLSS_JOB_CONTROL_RESUME:
7222                 if (print_job_resume(session_info, p->msg_ctx,
7223                                      snum, r->in.job_id, &errcode)) {
7224                         errcode = WERR_OK;
7225                 }
7226                 break;
7227         case 0:
7228                 errcode = WERR_OK;
7229                 break;
7230         default:
7231                 return WERR_UNKNOWN_LEVEL;
7232         }
7233
7234         if (!W_ERROR_IS_OK(errcode)) {
7235                 return errcode;
7236         }
7237
7238         if (r->in.ctr == NULL) {
7239                 return errcode;
7240         }
7241
7242         switch (r->in.ctr->level) {
7243         case 1:
7244                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7245                                            lp_const_servicename(snum),
7246                                            r->in.job_id,
7247                                            r->in.ctr->info.info1);
7248                 break;
7249         case 2:
7250         case 3:
7251         case 4:
7252         default:
7253                 return WERR_UNKNOWN_LEVEL;
7254         }
7255
7256         return errcode;
7257 }
7258
7259 /****************************************************************************
7260  Enumerates all printer drivers by level and architecture.
7261 ****************************************************************************/
7262
7263 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7264                                                        const struct auth_serversupplied_info *session_info,
7265                                                        struct messaging_context *msg_ctx,
7266                                                        const char *servername,
7267                                                        const char *architecture,
7268                                                        uint32_t level,
7269                                                        union spoolss_DriverInfo **info_p,
7270                                                        uint32_t *count_p)
7271 {
7272         int i;
7273         uint32_t version;
7274         struct spoolss_DriverInfo8 *driver;
7275         union spoolss_DriverInfo *info = NULL;
7276         uint32_t count = 0;
7277         WERROR result = WERR_OK;
7278         uint32_t num_drivers;
7279         const char **drivers;
7280
7281         *count_p = 0;
7282         *info_p = NULL;
7283
7284         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7285                 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7286                                                 architecture, version,
7287                                                 &num_drivers, &drivers);
7288                 if (!W_ERROR_IS_OK(result)) {
7289                         goto out;
7290                 }
7291                 DEBUG(4, ("we have:[%d] drivers in environment"
7292                           " [%s] and version [%d]\n",
7293                           num_drivers, architecture, version));
7294
7295                 if (num_drivers != 0) {
7296                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7297                                                     union spoolss_DriverInfo,
7298                                                     count + num_drivers);
7299                         if (!info) {
7300                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7301                                         "failed to enlarge driver info buffer!\n"));
7302                                 result = WERR_NOMEM;
7303                                 goto out;
7304                         }
7305                 }
7306
7307                 for (i = 0; i < num_drivers; i++) {
7308                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7309
7310                         result = winreg_get_driver(mem_ctx, session_info,
7311                                                    msg_ctx,
7312                                                    architecture, drivers[i],
7313                                                    version, &driver);
7314                         if (!W_ERROR_IS_OK(result)) {
7315                                 goto out;
7316                         }
7317
7318                         switch (level) {
7319                         case 1:
7320                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7321                                                                    driver, servername);
7322                                 break;
7323                         case 2:
7324                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7325                                                                    driver, servername);
7326                                 break;
7327                         case 3:
7328                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7329                                                                    driver, servername);
7330                                 break;
7331                         case 4:
7332                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7333                                                                    driver, servername);
7334                                 break;
7335                         case 5:
7336                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7337                                                                    driver, servername);
7338                                 break;
7339                         case 6:
7340                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7341                                                                    driver, servername);
7342                                 break;
7343                         case 8:
7344                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7345                                                                    driver, servername);
7346                                 break;
7347                         default:
7348                                 result = WERR_UNKNOWN_LEVEL;
7349                                 break;
7350                         }
7351
7352                         TALLOC_FREE(driver);
7353
7354                         if (!W_ERROR_IS_OK(result)) {
7355                                 goto out;
7356                         }
7357                 }
7358
7359                 count += num_drivers;
7360                 TALLOC_FREE(drivers);
7361         }
7362
7363  out:
7364         TALLOC_FREE(drivers);
7365
7366         if (!W_ERROR_IS_OK(result)) {
7367                 TALLOC_FREE(info);
7368                 return result;
7369         }
7370
7371         *info_p = info;
7372         *count_p = count;
7373
7374         return WERR_OK;
7375 }
7376
7377 /****************************************************************************
7378  Enumerates all printer drivers by level.
7379 ****************************************************************************/
7380
7381 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7382                                        const struct auth_serversupplied_info *session_info,
7383                                        struct messaging_context *msg_ctx,
7384                                        const char *servername,
7385                                        const char *architecture,
7386                                        uint32_t level,
7387                                        union spoolss_DriverInfo **info_p,
7388                                        uint32_t *count_p)
7389 {
7390         uint32_t a,i;
7391         WERROR result = WERR_OK;
7392
7393         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7394
7395                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7396
7397                         union spoolss_DriverInfo *info = NULL;
7398                         uint32_t count = 0;
7399
7400                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7401                                                                           session_info,
7402                                                                           msg_ctx,
7403                                                                           servername,
7404                                                                           archi_table[a].long_archi,
7405                                                                           level,
7406                                                                           &info,
7407                                                                           &count);
7408                         if (!W_ERROR_IS_OK(result)) {
7409                                 continue;
7410                         }
7411
7412                         for (i=0; i < count; i++) {
7413                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7414                                              info[i], info_p, count_p);
7415                         }
7416                 }
7417
7418                 return result;
7419         }
7420
7421         return enumprinterdrivers_level_by_architecture(mem_ctx,
7422                                                         session_info,
7423                                                         msg_ctx,
7424                                                         servername,
7425                                                         architecture,
7426                                                         level,
7427                                                         info_p,
7428                                                         count_p);
7429 }
7430
7431 /****************************************************************
7432  _spoolss_EnumPrinterDrivers
7433 ****************************************************************/
7434
7435 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7436                                    struct spoolss_EnumPrinterDrivers *r)
7437 {
7438         const char *cservername;
7439         WERROR result;
7440
7441         /* that's an [in out] buffer */
7442
7443         if (!r->in.buffer && (r->in.offered != 0)) {
7444                 return WERR_INVALID_PARAM;
7445         }
7446
7447         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7448
7449         *r->out.needed = 0;
7450         *r->out.count = 0;
7451         *r->out.info = NULL;
7452
7453         cservername = canon_servername(r->in.server);
7454
7455         if (!is_myname_or_ipaddr(cservername)) {
7456                 return WERR_UNKNOWN_PRINTER_DRIVER;
7457         }
7458
7459         result = enumprinterdrivers_level(p->mem_ctx,
7460                                           get_session_info_system(),
7461                                           p->msg_ctx,
7462                                           cservername,
7463                                           r->in.environment,
7464                                           r->in.level,
7465                                           r->out.info,
7466                                           r->out.count);
7467         if (!W_ERROR_IS_OK(result)) {
7468                 return result;
7469         }
7470
7471         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7472                                                      spoolss_EnumPrinterDrivers,
7473                                                      *r->out.info, r->in.level,
7474                                                      *r->out.count);
7475         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7476         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7477
7478         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7479 }
7480
7481 /****************************************************************
7482  _spoolss_EnumForms
7483 ****************************************************************/
7484
7485 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7486                           struct spoolss_EnumForms *r)
7487 {
7488         WERROR result;
7489
7490         *r->out.count = 0;
7491         *r->out.needed = 0;
7492         *r->out.info = NULL;
7493
7494         /* that's an [in out] buffer */
7495
7496         if (!r->in.buffer && (r->in.offered != 0) ) {
7497                 return WERR_INVALID_PARAM;
7498         }
7499
7500         DEBUG(4,("_spoolss_EnumForms\n"));
7501         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7502         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7503
7504         switch (r->in.level) {
7505         case 1:
7506                 result = winreg_printer_enumforms1(p->mem_ctx,
7507                                                    get_session_info_system(),
7508                                                    p->msg_ctx,
7509                                                    r->out.count,
7510                                                    r->out.info);
7511                 break;
7512         default:
7513                 result = WERR_UNKNOWN_LEVEL;
7514                 break;
7515         }
7516
7517         if (!W_ERROR_IS_OK(result)) {
7518                 return result;
7519         }
7520
7521         if (*r->out.count == 0) {
7522                 return WERR_NO_MORE_ITEMS;
7523         }
7524
7525         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7526                                                      spoolss_EnumForms,
7527                                                      *r->out.info, r->in.level,
7528                                                      *r->out.count);
7529         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7530         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7531
7532         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7533 }
7534
7535 /****************************************************************
7536  _spoolss_GetForm
7537 ****************************************************************/
7538
7539 WERROR _spoolss_GetForm(struct pipes_struct *p,
7540                         struct spoolss_GetForm *r)
7541 {
7542         WERROR result;
7543
7544         /* that's an [in out] buffer */
7545
7546         if (!r->in.buffer && (r->in.offered != 0)) {
7547                 return WERR_INVALID_PARAM;
7548         }
7549
7550         DEBUG(4,("_spoolss_GetForm\n"));
7551         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7552         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7553
7554         switch (r->in.level) {
7555         case 1:
7556                 result = winreg_printer_getform1(p->mem_ctx,
7557                                                  get_session_info_system(),
7558                                                  p->msg_ctx,
7559                                                  r->in.form_name,
7560                                                  &r->out.info->info1);
7561                 break;
7562         default:
7563                 result = WERR_UNKNOWN_LEVEL;
7564                 break;
7565         }
7566
7567         if (!W_ERROR_IS_OK(result)) {
7568                 TALLOC_FREE(r->out.info);
7569                 return result;
7570         }
7571
7572         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7573                                                r->out.info, r->in.level);
7574         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7575
7576         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7577 }
7578
7579 /****************************************************************************
7580 ****************************************************************************/
7581
7582 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7583                           struct spoolss_PortInfo1 *r,
7584                           const char *name)
7585 {
7586         r->port_name = talloc_strdup(mem_ctx, name);
7587         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7588
7589         return WERR_OK;
7590 }
7591
7592 /****************************************************************************
7593  TODO: This probably needs distinguish between TCP/IP and Local ports
7594  somehow.
7595 ****************************************************************************/
7596
7597 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7598                           struct spoolss_PortInfo2 *r,
7599                           const char *name)
7600 {
7601         r->port_name = talloc_strdup(mem_ctx, name);
7602         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7603
7604         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7605         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7606
7607         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7608         W_ERROR_HAVE_NO_MEMORY(r->description);
7609
7610         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7611         r->reserved = 0;
7612
7613         return WERR_OK;
7614 }
7615
7616
7617 /****************************************************************************
7618  wrapper around the enumer ports command
7619 ****************************************************************************/
7620
7621 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7622 {
7623         char *cmd = lp_enumports_cmd();
7624         char **qlines = NULL;
7625         char *command = NULL;
7626         int numlines;
7627         int ret;
7628         int fd;
7629
7630         *count = 0;
7631         *lines = NULL;
7632
7633         /* if no hook then just fill in the default port */
7634
7635         if ( !*cmd ) {
7636                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7637                         return WERR_NOMEM;
7638                 }
7639                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7640                         TALLOC_FREE(qlines);
7641                         return WERR_NOMEM;
7642                 }
7643                 qlines[1] = NULL;
7644                 numlines = 1;
7645         }
7646         else {
7647                 /* we have a valid enumport command */
7648
7649                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7650                 if (!command) {
7651                         return WERR_NOMEM;
7652                 }
7653
7654                 DEBUG(10,("Running [%s]\n", command));
7655                 ret = smbrun(command, &fd);
7656                 DEBUG(10,("Returned [%d]\n", ret));
7657                 TALLOC_FREE(command);
7658                 if (ret != 0) {
7659                         if (fd != -1) {
7660                                 close(fd);
7661                         }
7662                         return WERR_ACCESS_DENIED;
7663                 }
7664
7665                 numlines = 0;
7666                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7667                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7668                 close(fd);
7669         }
7670
7671         *count = numlines;
7672         *lines = qlines;
7673
7674         return WERR_OK;
7675 }
7676
7677 /****************************************************************************
7678  enumports level 1.
7679 ****************************************************************************/
7680
7681 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7682                                 union spoolss_PortInfo **info_p,
7683                                 uint32_t *count)
7684 {
7685         union spoolss_PortInfo *info = NULL;
7686         int i=0;
7687         WERROR result = WERR_OK;
7688         char **qlines = NULL;
7689         int numlines = 0;
7690
7691         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7692         if (!W_ERROR_IS_OK(result)) {
7693                 goto out;
7694         }
7695
7696         if (numlines) {
7697                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7698                 if (!info) {
7699                         DEBUG(10,("Returning WERR_NOMEM\n"));
7700                         result = WERR_NOMEM;
7701                         goto out;
7702                 }
7703
7704                 for (i=0; i<numlines; i++) {
7705                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7706                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7707                         if (!W_ERROR_IS_OK(result)) {
7708                                 goto out;
7709                         }
7710                 }
7711         }
7712         TALLOC_FREE(qlines);
7713
7714 out:
7715         if (!W_ERROR_IS_OK(result)) {
7716                 TALLOC_FREE(info);
7717                 TALLOC_FREE(qlines);
7718                 *count = 0;
7719                 *info_p = NULL;
7720                 return result;
7721         }
7722
7723         *info_p = info;
7724         *count = numlines;
7725
7726         return WERR_OK;
7727 }
7728
7729 /****************************************************************************
7730  enumports level 2.
7731 ****************************************************************************/
7732
7733 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7734                                 union spoolss_PortInfo **info_p,
7735                                 uint32_t *count)
7736 {
7737         union spoolss_PortInfo *info = NULL;
7738         int i=0;
7739         WERROR result = WERR_OK;
7740         char **qlines = NULL;
7741         int numlines = 0;
7742
7743         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7744         if (!W_ERROR_IS_OK(result)) {
7745                 goto out;
7746         }
7747
7748         if (numlines) {
7749                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7750                 if (!info) {
7751                         DEBUG(10,("Returning WERR_NOMEM\n"));
7752                         result = WERR_NOMEM;
7753                         goto out;
7754                 }
7755
7756                 for (i=0; i<numlines; i++) {
7757                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7758                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7759                         if (!W_ERROR_IS_OK(result)) {
7760                                 goto out;
7761                         }
7762                 }
7763         }
7764         TALLOC_FREE(qlines);
7765
7766 out:
7767         if (!W_ERROR_IS_OK(result)) {
7768                 TALLOC_FREE(info);
7769                 TALLOC_FREE(qlines);
7770                 *count = 0;
7771                 *info_p = NULL;
7772                 return result;
7773         }
7774
7775         *info_p = info;
7776         *count = numlines;
7777
7778         return WERR_OK;
7779 }
7780
7781 /****************************************************************
7782  _spoolss_EnumPorts
7783 ****************************************************************/
7784
7785 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7786                           struct spoolss_EnumPorts *r)
7787 {
7788         WERROR result;
7789
7790         /* that's an [in out] buffer */
7791
7792         if (!r->in.buffer && (r->in.offered != 0)) {
7793                 return WERR_INVALID_PARAM;
7794         }
7795
7796         DEBUG(4,("_spoolss_EnumPorts\n"));
7797
7798         *r->out.count = 0;
7799         *r->out.needed = 0;
7800         *r->out.info = NULL;
7801
7802         switch (r->in.level) {
7803         case 1:
7804                 result = enumports_level_1(p->mem_ctx, r->out.info,
7805                                            r->out.count);
7806                 break;
7807         case 2:
7808                 result = enumports_level_2(p->mem_ctx, r->out.info,
7809                                            r->out.count);
7810                 break;
7811         default:
7812                 return WERR_UNKNOWN_LEVEL;
7813         }
7814
7815         if (!W_ERROR_IS_OK(result)) {
7816                 return result;
7817         }
7818
7819         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7820                                                      spoolss_EnumPorts,
7821                                                      *r->out.info, r->in.level,
7822                                                      *r->out.count);
7823         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7824         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7825
7826         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7827 }
7828
7829 /****************************************************************************
7830 ****************************************************************************/
7831
7832 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7833                                            const char *server,
7834                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7835                                            struct spoolss_DeviceMode *devmode,
7836                                            struct security_descriptor *secdesc,
7837                                            struct spoolss_UserLevelCtr *user_ctr,
7838                                            struct policy_handle *handle)
7839 {
7840         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7841         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7842         int     snum;
7843         WERROR err = WERR_OK;
7844
7845         /* samba does not have a concept of local, non-shared printers yet, so
7846          * make sure we always setup sharename - gd */
7847         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7848             (info2->printername != NULL && info2->printername[0] != '\0')) {
7849                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7850                         "no sharename has been set, setting printername %s as sharename\n",
7851                         info2->printername));
7852                 info2->sharename = info2->printername;
7853         }
7854
7855         /* check to see if the printer already exists */
7856         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7857                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7858                         info2->sharename));
7859                 return WERR_PRINTER_ALREADY_EXISTS;
7860         }
7861
7862         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7863                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7864                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7865                                 info2->printername));
7866                         return WERR_PRINTER_ALREADY_EXISTS;
7867                 }
7868         }
7869
7870         /* validate printer info struct */
7871         if (!info2->printername || strlen(info2->printername) == 0) {
7872                 return WERR_INVALID_PRINTER_NAME;
7873         }
7874         if (!info2->portname || strlen(info2->portname) == 0) {
7875                 return WERR_UNKNOWN_PORT;
7876         }
7877         if (!info2->drivername || strlen(info2->drivername) == 0) {
7878                 return WERR_UNKNOWN_PRINTER_DRIVER;
7879         }
7880         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7881                 return WERR_UNKNOWN_PRINTPROCESSOR;
7882         }
7883
7884         /* FIXME!!!  smbd should check to see if the driver is installed before
7885            trying to add a printer like this  --jerry */
7886
7887         if (*lp_addprinter_cmd() ) {
7888                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7889                                        info2, p->client_id->addr,
7890                                        p->msg_ctx) ) {
7891                         return WERR_ACCESS_DENIED;
7892                 }
7893         } else {
7894                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7895                         "smb.conf parameter \"addprinter command\" is defined. This "
7896                         "parameter must exist for this call to succeed\n",
7897                         info2->sharename ));
7898         }
7899
7900         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7901                 return WERR_ACCESS_DENIED;
7902         }
7903
7904         /* you must be a printer admin to add a new printer */
7905         if (!print_access_check(p->session_info,
7906                                 p->msg_ctx,
7907                                 snum,
7908                                 PRINTER_ACCESS_ADMINISTER)) {
7909                 return WERR_ACCESS_DENIED;
7910         }
7911
7912         /*
7913          * Do sanity check on the requested changes for Samba.
7914          */
7915
7916         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7917                 return WERR_INVALID_PARAM;
7918         }
7919
7920         if (devmode == NULL) {
7921                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7922         }
7923
7924         update_dsspooler(p->mem_ctx,
7925                          get_session_info_system(),
7926                          p->msg_ctx,
7927                          0,
7928                          info2,
7929                          NULL);
7930
7931         err = winreg_update_printer(p->mem_ctx,
7932                                     get_session_info_system(),
7933                                     p->msg_ctx,
7934                                     info2->sharename,
7935                                     info2_mask,
7936                                     info2,
7937                                     devmode,
7938                                     secdesc);
7939         if (!W_ERROR_IS_OK(err)) {
7940                 return err;
7941         }
7942
7943         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7944         if (!W_ERROR_IS_OK(err)) {
7945                 /* Handle open failed - remove addition. */
7946                 ZERO_STRUCTP(handle);
7947                 return err;
7948         }
7949
7950         return WERR_OK;
7951 }
7952
7953 /****************************************************************
7954  _spoolss_AddPrinterEx
7955 ****************************************************************/
7956
7957 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7958                              struct spoolss_AddPrinterEx *r)
7959 {
7960         switch (r->in.info_ctr->level) {
7961         case 1:
7962                 /* we don't handle yet */
7963                 /* but I know what to do ... */
7964                 return WERR_UNKNOWN_LEVEL;
7965         case 2:
7966                 return spoolss_addprinterex_level_2(p, r->in.server,
7967                                                     r->in.info_ctr,
7968                                                     r->in.devmode_ctr->devmode,
7969                                                     r->in.secdesc_ctr->sd,
7970                                                     r->in.userlevel_ctr,
7971                                                     r->out.handle);
7972         default:
7973                 return WERR_UNKNOWN_LEVEL;
7974         }
7975 }
7976
7977 /****************************************************************
7978  _spoolss_AddPrinter
7979 ****************************************************************/
7980
7981 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7982                            struct spoolss_AddPrinter *r)
7983 {
7984         struct spoolss_AddPrinterEx a;
7985         struct spoolss_UserLevelCtr userlevel_ctr;
7986
7987         ZERO_STRUCT(userlevel_ctr);
7988
7989         userlevel_ctr.level = 1;
7990
7991         a.in.server             = r->in.server;
7992         a.in.info_ctr           = r->in.info_ctr;
7993         a.in.devmode_ctr        = r->in.devmode_ctr;
7994         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7995         a.in.userlevel_ctr      = &userlevel_ctr;
7996         a.out.handle            = r->out.handle;
7997
7998         return _spoolss_AddPrinterEx(p, &a);
7999 }
8000
8001 /****************************************************************
8002  _spoolss_AddPrinterDriverEx
8003 ****************************************************************/
8004
8005 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8006                                    struct spoolss_AddPrinterDriverEx *r)
8007 {
8008         WERROR err = WERR_OK;
8009         const char *driver_name = NULL;
8010         uint32_t version;
8011         const char *fn;
8012
8013         switch (p->opnum) {
8014                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8015                         fn = "_spoolss_AddPrinterDriver";
8016                         break;
8017                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8018                         fn = "_spoolss_AddPrinterDriverEx";
8019                         break;
8020                 default:
8021                         return WERR_INVALID_PARAM;
8022         }
8023
8024         /*
8025          * we only support the semantics of AddPrinterDriver()
8026          * i.e. only copy files that are newer than existing ones
8027          */
8028
8029         if (r->in.flags == 0) {
8030                 return WERR_INVALID_PARAM;
8031         }
8032
8033         if (r->in.flags != APD_COPY_NEW_FILES) {
8034                 return WERR_ACCESS_DENIED;
8035         }
8036
8037         /* FIXME */
8038         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8039                 /* Clever hack from Martin Zielinski <mz@seh.de>
8040                  * to allow downgrade from level 8 (Vista).
8041                  */
8042                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8043                         r->in.info_ctr->level));
8044                 return WERR_UNKNOWN_LEVEL;
8045         }
8046
8047         DEBUG(5,("Cleaning driver's information\n"));
8048         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8049         if (!W_ERROR_IS_OK(err))
8050                 goto done;
8051
8052         DEBUG(5,("Moving driver to final destination\n"));
8053         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8054         if (!W_ERROR_IS_OK(err)) {
8055                 goto done;
8056         }
8057
8058         err = winreg_add_driver(p->mem_ctx,
8059                                 get_session_info_system(),
8060                                 p->msg_ctx,
8061                                 r->in.info_ctr,
8062                                 &driver_name,
8063                                 &version);
8064         if (!W_ERROR_IS_OK(err)) {
8065                 goto done;
8066         }
8067
8068         /*
8069          * I think this is where he DrvUpgradePrinter() hook would be
8070          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8071          * server.  Right now, we just need to send ourselves a message
8072          * to update each printer bound to this driver.   --jerry
8073          */
8074
8075         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8076                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8077                         fn, driver_name));
8078         }
8079
8080 done:
8081         return err;
8082 }
8083
8084 /****************************************************************
8085  _spoolss_AddPrinterDriver
8086 ****************************************************************/
8087
8088 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8089                                  struct spoolss_AddPrinterDriver *r)
8090 {
8091         struct spoolss_AddPrinterDriverEx a;
8092
8093         switch (r->in.info_ctr->level) {
8094         case 2:
8095         case 3:
8096         case 4:
8097         case 5:
8098                 break;
8099         default:
8100                 return WERR_UNKNOWN_LEVEL;
8101         }
8102
8103         a.in.servername         = r->in.servername;
8104         a.in.info_ctr           = r->in.info_ctr;
8105         a.in.flags              = APD_COPY_NEW_FILES;
8106
8107         return _spoolss_AddPrinterDriverEx(p, &a);
8108 }
8109
8110 /****************************************************************************
8111 ****************************************************************************/
8112
8113 struct _spoolss_paths {
8114         int type;
8115         const char *share;
8116         const char *dir;
8117 };
8118
8119 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8120
8121 static const struct _spoolss_paths spoolss_paths[]= {
8122         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8123         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8124 };
8125
8126 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8127                                           const char *servername,
8128                                           const char *environment,
8129                                           int component,
8130                                           char **path)
8131 {
8132         const char *pservername = NULL;
8133         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8134         const char *short_archi;
8135
8136         *path = NULL;
8137
8138         /* environment may be empty */
8139         if (environment && strlen(environment)) {
8140                 long_archi = environment;
8141         }
8142
8143         /* servername may be empty */
8144         if (servername && strlen(servername)) {
8145                 pservername = canon_servername(servername);
8146
8147                 if (!is_myname_or_ipaddr(pservername)) {
8148                         return WERR_INVALID_PARAM;
8149                 }
8150         }
8151
8152         if (!(short_archi = get_short_archi(long_archi))) {
8153                 return WERR_INVALID_ENVIRONMENT;
8154         }
8155
8156         switch (component) {
8157         case SPOOLSS_PRTPROCS_PATH:
8158         case SPOOLSS_DRIVER_PATH:
8159                 if (pservername) {
8160                         *path = talloc_asprintf(mem_ctx,
8161                                         "\\\\%s\\%s\\%s",
8162                                         pservername,
8163                                         spoolss_paths[component].share,
8164                                         short_archi);
8165                 } else {
8166                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8167                                         SPOOLSS_DEFAULT_SERVER_PATH,
8168                                         spoolss_paths[component].dir,
8169                                         short_archi);
8170                 }
8171                 break;
8172         default:
8173                 return WERR_INVALID_PARAM;
8174         }
8175
8176         if (!*path) {
8177                 return WERR_NOMEM;
8178         }
8179
8180         return WERR_OK;
8181 }
8182
8183 /****************************************************************************
8184 ****************************************************************************/
8185
8186 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8187                                           const char *servername,
8188                                           const char *environment,
8189                                           struct spoolss_DriverDirectoryInfo1 *r)
8190 {
8191         WERROR werr;
8192         char *path = NULL;
8193
8194         werr = compose_spoolss_server_path(mem_ctx,
8195                                            servername,
8196                                            environment,
8197                                            SPOOLSS_DRIVER_PATH,
8198                                            &path);
8199         if (!W_ERROR_IS_OK(werr)) {
8200                 return werr;
8201         }
8202
8203         DEBUG(4,("printer driver directory: [%s]\n", path));
8204
8205         r->directory_name = path;
8206
8207         return WERR_OK;
8208 }
8209
8210 /****************************************************************
8211  _spoolss_GetPrinterDriverDirectory
8212 ****************************************************************/
8213
8214 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8215                                           struct spoolss_GetPrinterDriverDirectory *r)
8216 {
8217         WERROR werror;
8218
8219         /* that's an [in out] buffer */
8220
8221         if (!r->in.buffer && (r->in.offered != 0)) {
8222                 return WERR_INVALID_PARAM;
8223         }
8224
8225         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8226                 r->in.level));
8227
8228         *r->out.needed = 0;
8229
8230         /* r->in.level is ignored */
8231
8232         werror = getprinterdriverdir_level_1(p->mem_ctx,
8233                                              r->in.server,
8234                                              r->in.environment,
8235                                              &r->out.info->info1);
8236         if (!W_ERROR_IS_OK(werror)) {
8237                 TALLOC_FREE(r->out.info);
8238                 return werror;
8239         }
8240
8241         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8242                                                r->out.info, r->in.level);
8243         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8244
8245         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8246 }
8247
8248 /****************************************************************
8249  _spoolss_EnumPrinterData
8250 ****************************************************************/
8251
8252 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8253                                 struct spoolss_EnumPrinterData *r)
8254 {
8255         WERROR result;
8256         struct spoolss_EnumPrinterDataEx r2;
8257         uint32_t count;
8258         struct spoolss_PrinterEnumValues *info, *val = NULL;
8259         uint32_t needed;
8260
8261         r2.in.handle    = r->in.handle;
8262         r2.in.key_name  = "PrinterDriverData";
8263         r2.in.offered   = 0;
8264         r2.out.count    = &count;
8265         r2.out.info     = &info;
8266         r2.out.needed   = &needed;
8267
8268         result = _spoolss_EnumPrinterDataEx(p, &r2);
8269         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8270                 r2.in.offered = needed;
8271                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8272         }
8273         if (!W_ERROR_IS_OK(result)) {
8274                 return result;
8275         }
8276
8277         /*
8278          * The NT machine wants to know the biggest size of value and data
8279          *
8280          * cf: MSDN EnumPrinterData remark section
8281          */
8282
8283         if (!r->in.value_offered && !r->in.data_offered) {
8284                 uint32_t biggest_valuesize = 0;
8285                 uint32_t biggest_datasize = 0;
8286                 int i, name_length;
8287
8288                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8289
8290                 for (i=0; i<count; i++) {
8291
8292                         name_length = strlen(info[i].value_name);
8293                         if (strlen(info[i].value_name) > biggest_valuesize) {
8294                                 biggest_valuesize = name_length;
8295                         }
8296
8297                         if (info[i].data_length > biggest_datasize) {
8298                                 biggest_datasize = info[i].data_length;
8299                         }
8300
8301                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8302                                 biggest_datasize));
8303                 }
8304
8305                 /* the value is an UNICODE string but real_value_size is the length
8306                    in bytes including the trailing 0 */
8307
8308                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8309                 *r->out.data_needed  = biggest_datasize;
8310
8311                 DEBUG(6,("final values: [%d], [%d]\n",
8312                         *r->out.value_needed, *r->out.data_needed));
8313
8314                 return WERR_OK;
8315         }
8316
8317         if (r->in.enum_index < count) {
8318                 val = &info[r->in.enum_index];
8319         }
8320
8321         if (val == NULL) {
8322                 /* out_value should default to "" or else NT4 has
8323                    problems unmarshalling the response */
8324
8325                 if (r->in.value_offered) {
8326                         *r->out.value_needed = 1;
8327                         r->out.value_name = talloc_strdup(r, "");
8328                         if (!r->out.value_name) {
8329                                 return WERR_NOMEM;
8330                         }
8331                 } else {
8332                         r->out.value_name = NULL;
8333                         *r->out.value_needed = 0;
8334                 }
8335
8336                 /* the data is counted in bytes */
8337
8338                 *r->out.data_needed = r->in.data_offered;
8339
8340                 result = WERR_NO_MORE_ITEMS;
8341         } else {
8342                 /*
8343                  * the value is:
8344                  * - counted in bytes in the request
8345                  * - counted in UNICODE chars in the max reply
8346                  * - counted in bytes in the real size
8347                  *
8348                  * take a pause *before* coding not *during* coding
8349                  */
8350
8351                 /* name */
8352                 if (r->in.value_offered) {
8353                         r->out.value_name = talloc_strdup(r, val->value_name);
8354                         if (!r->out.value_name) {
8355                                 return WERR_NOMEM;
8356                         }
8357                         *r->out.value_needed = val->value_name_len;
8358                 } else {
8359                         r->out.value_name = NULL;
8360                         *r->out.value_needed = 0;
8361                 }
8362
8363                 /* type */
8364
8365                 *r->out.type = val->type;
8366
8367                 /* data - counted in bytes */
8368
8369                 /*
8370                  * See the section "Dynamically Typed Query Parameters"
8371                  * in MS-RPRN.
8372                  */
8373
8374                 if (r->out.data && val->data && val->data->data &&
8375                                 val->data_length && r->in.data_offered) {
8376                         memcpy(r->out.data, val->data->data,
8377                                 MIN(val->data_length,r->in.data_offered));
8378                 }
8379
8380                 *r->out.data_needed = val->data_length;
8381
8382                 result = WERR_OK;
8383         }
8384
8385         return result;
8386 }
8387
8388 /****************************************************************
8389  _spoolss_SetPrinterData
8390 ****************************************************************/
8391
8392 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8393                                struct spoolss_SetPrinterData *r)
8394 {
8395         struct spoolss_SetPrinterDataEx r2;
8396
8397         r2.in.handle            = r->in.handle;
8398         r2.in.key_name          = "PrinterDriverData";
8399         r2.in.value_name        = r->in.value_name;
8400         r2.in.type              = r->in.type;
8401         r2.in.data              = r->in.data;
8402         r2.in.offered           = r->in.offered;
8403
8404         return _spoolss_SetPrinterDataEx(p, &r2);
8405 }
8406
8407 /****************************************************************
8408  _spoolss_ResetPrinter
8409 ****************************************************************/
8410
8411 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8412                              struct spoolss_ResetPrinter *r)
8413 {
8414         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8415         int             snum;
8416
8417         DEBUG(5,("_spoolss_ResetPrinter\n"));
8418
8419         /*
8420          * All we do is to check to see if the handle and queue is valid.
8421          * This call really doesn't mean anything to us because we only
8422          * support RAW printing.   --jerry
8423          */
8424
8425         if (!Printer) {
8426                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8427                         OUR_HANDLE(r->in.handle)));
8428                 return WERR_BADFID;
8429         }
8430
8431         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8432                 return WERR_BADFID;
8433
8434
8435         /* blindly return success */
8436         return WERR_OK;
8437 }
8438
8439 /****************************************************************
8440  _spoolss_DeletePrinterData
8441 ****************************************************************/
8442
8443 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8444                                   struct spoolss_DeletePrinterData *r)
8445 {
8446         struct spoolss_DeletePrinterDataEx r2;
8447
8448         r2.in.handle            = r->in.handle;
8449         r2.in.key_name          = "PrinterDriverData";
8450         r2.in.value_name        = r->in.value_name;
8451
8452         return _spoolss_DeletePrinterDataEx(p, &r2);
8453 }
8454
8455 /****************************************************************
8456  _spoolss_AddForm
8457 ****************************************************************/
8458
8459 WERROR _spoolss_AddForm(struct pipes_struct *p,
8460                         struct spoolss_AddForm *r)
8461 {
8462         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8463         int snum = -1;
8464         WERROR status = WERR_OK;
8465
8466         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8467
8468         DEBUG(5,("_spoolss_AddForm\n"));
8469
8470         if (!Printer) {
8471                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8472                         OUR_HANDLE(r->in.handle)));
8473                 return WERR_BADFID;
8474         }
8475
8476         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8477            and not a printer admin, then fail */
8478
8479         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8480             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8481             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8482                                           p->session_info->info3->base.domain.string,
8483                                           NULL,
8484                                           p->session_info->security_token,
8485                                           lp_printer_admin(snum))) {
8486                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8487                 return WERR_ACCESS_DENIED;
8488         }
8489
8490         switch (form->flags) {
8491         case SPOOLSS_FORM_USER:
8492         case SPOOLSS_FORM_BUILTIN:
8493         case SPOOLSS_FORM_PRINTER:
8494                 break;
8495         default:
8496                 return WERR_INVALID_PARAM;
8497         }
8498
8499         status = winreg_printer_addform1(p->mem_ctx,
8500                                          get_session_info_system(),
8501                                          p->msg_ctx,
8502                                          form);
8503         if (!W_ERROR_IS_OK(status)) {
8504                 return status;
8505         }
8506
8507         /*
8508          * ChangeID must always be set if this is a printer
8509          */
8510         if (Printer->printer_type == SPLHND_PRINTER) {
8511                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8512                         return WERR_BADFID;
8513                 }
8514
8515                 status = winreg_printer_update_changeid(p->mem_ctx,
8516                                                         get_session_info_system(),
8517                                                         p->msg_ctx,
8518                                                         lp_const_servicename(snum));
8519                 if (!W_ERROR_IS_OK(status)) {
8520                         return status;
8521                 }
8522         }
8523
8524         return status;
8525 }
8526
8527 /****************************************************************
8528  _spoolss_DeleteForm
8529 ****************************************************************/
8530
8531 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8532                            struct spoolss_DeleteForm *r)
8533 {
8534         const char *form_name = r->in.form_name;
8535         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8536         int snum = -1;
8537         WERROR status = WERR_OK;
8538
8539         DEBUG(5,("_spoolss_DeleteForm\n"));
8540
8541         if (!Printer) {
8542                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8543                         OUR_HANDLE(r->in.handle)));
8544                 return WERR_BADFID;
8545         }
8546
8547         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8548             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8549             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8550                                           p->session_info->info3->base.domain.string,
8551                                           NULL,
8552                                           p->session_info->security_token,
8553                                           lp_printer_admin(snum))) {
8554                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8555                 return WERR_ACCESS_DENIED;
8556         }
8557
8558         status = winreg_printer_deleteform1(p->mem_ctx,
8559                                             get_session_info_system(),
8560                                             p->msg_ctx,
8561                                             form_name);
8562         if (!W_ERROR_IS_OK(status)) {
8563                 return status;
8564         }
8565
8566         /*
8567          * ChangeID must always be set if this is a printer
8568          */
8569         if (Printer->printer_type == SPLHND_PRINTER) {
8570                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8571                         return WERR_BADFID;
8572                 }
8573
8574                 status = winreg_printer_update_changeid(p->mem_ctx,
8575                                                         get_session_info_system(),
8576                                                         p->msg_ctx,
8577                                                         lp_const_servicename(snum));
8578                 if (!W_ERROR_IS_OK(status)) {
8579                         return status;
8580                 }
8581         }
8582
8583         return status;
8584 }
8585
8586 /****************************************************************
8587  _spoolss_SetForm
8588 ****************************************************************/
8589
8590 WERROR _spoolss_SetForm(struct pipes_struct *p,
8591                         struct spoolss_SetForm *r)
8592 {
8593         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8594         const char *form_name = r->in.form_name;
8595         int snum = -1;
8596         WERROR status = WERR_OK;
8597
8598         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8599
8600         DEBUG(5,("_spoolss_SetForm\n"));
8601
8602         if (!Printer) {
8603                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8604                         OUR_HANDLE(r->in.handle)));
8605                 return WERR_BADFID;
8606         }
8607
8608         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8609            and not a printer admin, then fail */
8610
8611         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8612              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8613              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8614                                           p->session_info->info3->base.domain.string,
8615                                           NULL,
8616                                           p->session_info->security_token,
8617                                           lp_printer_admin(snum))) {
8618                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8619                 return WERR_ACCESS_DENIED;
8620         }
8621
8622         status = winreg_printer_setform1(p->mem_ctx,
8623                                          get_session_info_system(),
8624                                          p->msg_ctx,
8625                                          form_name,
8626                                          form);
8627         if (!W_ERROR_IS_OK(status)) {
8628                 return status;
8629         }
8630
8631         /*
8632          * ChangeID must always be set if this is a printer
8633          */
8634         if (Printer->printer_type == SPLHND_PRINTER) {
8635                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8636                         return WERR_BADFID;
8637                 }
8638
8639                 status = winreg_printer_update_changeid(p->mem_ctx,
8640                                                         get_session_info_system(),
8641                                                         p->msg_ctx,
8642                                                         lp_const_servicename(snum));
8643                 if (!W_ERROR_IS_OK(status)) {
8644                         return status;
8645                 }
8646         }
8647
8648         return status;
8649 }
8650
8651 /****************************************************************************
8652  fill_print_processor1
8653 ****************************************************************************/
8654
8655 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8656                                     struct spoolss_PrintProcessorInfo1 *r,
8657                                     const char *print_processor_name)
8658 {
8659         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8660         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8661
8662         return WERR_OK;
8663 }
8664
8665 /****************************************************************************
8666  enumprintprocessors level 1.
8667 ****************************************************************************/
8668
8669 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8670                                           union spoolss_PrintProcessorInfo **info_p,
8671                                           uint32_t *count)
8672 {
8673         union spoolss_PrintProcessorInfo *info;
8674         WERROR result;
8675
8676         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8677         W_ERROR_HAVE_NO_MEMORY(info);
8678
8679         *count = 1;
8680
8681         result = fill_print_processor1(info, &info[0].info1, "winprint");
8682         if (!W_ERROR_IS_OK(result)) {
8683                 goto out;
8684         }
8685
8686  out:
8687         if (!W_ERROR_IS_OK(result)) {
8688                 TALLOC_FREE(info);
8689                 *count = 0;
8690                 return result;
8691         }
8692
8693         *info_p = info;
8694
8695         return WERR_OK;
8696 }
8697
8698 /****************************************************************
8699  _spoolss_EnumPrintProcessors
8700 ****************************************************************/
8701
8702 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8703                                     struct spoolss_EnumPrintProcessors *r)
8704 {
8705         WERROR result;
8706
8707         /* that's an [in out] buffer */
8708
8709         if (!r->in.buffer && (r->in.offered != 0)) {
8710                 return WERR_INVALID_PARAM;
8711         }
8712
8713         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8714
8715         /*
8716          * Enumerate the print processors ...
8717          *
8718          * Just reply with "winprint", to keep NT happy
8719          * and I can use my nice printer checker.
8720          */
8721
8722         *r->out.count = 0;
8723         *r->out.needed = 0;
8724         *r->out.info = NULL;
8725
8726         if (!get_short_archi(r->in.environment)) {
8727                 return WERR_INVALID_ENVIRONMENT;
8728         }
8729
8730         switch (r->in.level) {
8731         case 1:
8732                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8733                                                      r->out.count);
8734                 break;
8735         default:
8736                 return WERR_UNKNOWN_LEVEL;
8737         }
8738
8739         if (!W_ERROR_IS_OK(result)) {
8740                 return result;
8741         }
8742
8743         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8744                                                      spoolss_EnumPrintProcessors,
8745                                                      *r->out.info, r->in.level,
8746                                                      *r->out.count);
8747         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8748         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8749
8750         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8751 }
8752
8753 /****************************************************************************
8754  fill_printprocdatatype1
8755 ****************************************************************************/
8756
8757 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8758                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8759                                       const char *name_array)
8760 {
8761         r->name_array = talloc_strdup(mem_ctx, name_array);
8762         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8763
8764         return WERR_OK;
8765 }
8766
8767 /****************************************************************************
8768  enumprintprocdatatypes level 1.
8769 ****************************************************************************/
8770
8771 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8772                                              union spoolss_PrintProcDataTypesInfo **info_p,
8773                                              uint32_t *count)
8774 {
8775         WERROR result;
8776         union spoolss_PrintProcDataTypesInfo *info;
8777
8778         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8779         W_ERROR_HAVE_NO_MEMORY(info);
8780
8781         *count = 1;
8782
8783         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8784         if (!W_ERROR_IS_OK(result)) {
8785                 goto out;
8786         }
8787
8788  out:
8789         if (!W_ERROR_IS_OK(result)) {
8790                 TALLOC_FREE(info);
8791                 *count = 0;
8792                 return result;
8793         }
8794
8795         *info_p = info;
8796
8797         return WERR_OK;
8798 }
8799
8800 /****************************************************************
8801  _spoolss_EnumPrintProcDataTypes
8802 ****************************************************************/
8803
8804 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8805                                        struct spoolss_EnumPrintProcDataTypes *r)
8806 {
8807         WERROR result;
8808
8809         /* that's an [in out] buffer */
8810
8811         if (!r->in.buffer && (r->in.offered != 0)) {
8812                 return WERR_INVALID_PARAM;
8813         }
8814
8815         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8816
8817         *r->out.count = 0;
8818         *r->out.needed = 0;
8819         *r->out.info = NULL;
8820
8821         if (r->in.print_processor_name == NULL ||
8822             !strequal(r->in.print_processor_name, "winprint")) {
8823                 return WERR_UNKNOWN_PRINTPROCESSOR;
8824         }
8825
8826         switch (r->in.level) {
8827         case 1:
8828                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8829                                                         r->out.count);
8830                 break;
8831         default:
8832                 return WERR_UNKNOWN_LEVEL;
8833         }
8834
8835         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8836                                                      spoolss_EnumPrintProcDataTypes,
8837                                                      *r->out.info, r->in.level,
8838                                                      *r->out.count);
8839         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8840         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8841
8842         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8843 }
8844
8845 /****************************************************************************
8846  fill_monitor_1
8847 ****************************************************************************/
8848
8849 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8850                              struct spoolss_MonitorInfo1 *r,
8851                              const char *monitor_name)
8852 {
8853         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8854         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8855
8856         return WERR_OK;
8857 }
8858
8859 /****************************************************************************
8860  fill_monitor_2
8861 ****************************************************************************/
8862
8863 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8864                              struct spoolss_MonitorInfo2 *r,
8865                              const char *monitor_name,
8866                              const char *environment,
8867                              const char *dll_name)
8868 {
8869         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8870         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8871         r->environment                  = talloc_strdup(mem_ctx, environment);
8872         W_ERROR_HAVE_NO_MEMORY(r->environment);
8873         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8874         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8875
8876         return WERR_OK;
8877 }
8878
8879 /****************************************************************************
8880  enumprintmonitors level 1.
8881 ****************************************************************************/
8882
8883 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8884                                         union spoolss_MonitorInfo **info_p,
8885                                         uint32_t *count)
8886 {
8887         union spoolss_MonitorInfo *info;
8888         WERROR result = WERR_OK;
8889
8890         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8891         W_ERROR_HAVE_NO_MEMORY(info);
8892
8893         *count = 2;
8894
8895         result = fill_monitor_1(info, &info[0].info1,
8896                                 SPL_LOCAL_PORT);
8897         if (!W_ERROR_IS_OK(result)) {
8898                 goto out;
8899         }
8900
8901         result = fill_monitor_1(info, &info[1].info1,
8902                                 SPL_TCPIP_PORT);
8903         if (!W_ERROR_IS_OK(result)) {
8904                 goto out;
8905         }
8906
8907 out:
8908         if (!W_ERROR_IS_OK(result)) {
8909                 TALLOC_FREE(info);
8910                 *count = 0;
8911                 return result;
8912         }
8913
8914         *info_p = info;
8915
8916         return WERR_OK;
8917 }
8918
8919 /****************************************************************************
8920  enumprintmonitors level 2.
8921 ****************************************************************************/
8922
8923 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8924                                         union spoolss_MonitorInfo **info_p,
8925                                         uint32_t *count)
8926 {
8927         union spoolss_MonitorInfo *info;
8928         WERROR result = WERR_OK;
8929
8930         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8931         W_ERROR_HAVE_NO_MEMORY(info);
8932
8933         *count = 2;
8934
8935         result = fill_monitor_2(info, &info[0].info2,
8936                                 SPL_LOCAL_PORT,
8937                                 "Windows NT X86", /* FIXME */
8938                                 "localmon.dll");
8939         if (!W_ERROR_IS_OK(result)) {
8940                 goto out;
8941         }
8942
8943         result = fill_monitor_2(info, &info[1].info2,
8944                                 SPL_TCPIP_PORT,
8945                                 "Windows NT X86", /* FIXME */
8946                                 "tcpmon.dll");
8947         if (!W_ERROR_IS_OK(result)) {
8948                 goto out;
8949         }
8950
8951 out:
8952         if (!W_ERROR_IS_OK(result)) {
8953                 TALLOC_FREE(info);
8954                 *count = 0;
8955                 return result;
8956         }
8957
8958         *info_p = info;
8959
8960         return WERR_OK;
8961 }
8962
8963 /****************************************************************
8964  _spoolss_EnumMonitors
8965 ****************************************************************/
8966
8967 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8968                              struct spoolss_EnumMonitors *r)
8969 {
8970         WERROR result;
8971
8972         /* that's an [in out] buffer */
8973
8974         if (!r->in.buffer && (r->in.offered != 0)) {
8975                 return WERR_INVALID_PARAM;
8976         }
8977
8978         DEBUG(5,("_spoolss_EnumMonitors\n"));
8979
8980         /*
8981          * Enumerate the print monitors ...
8982          *
8983          * Just reply with "Local Port", to keep NT happy
8984          * and I can use my nice printer checker.
8985          */
8986
8987         *r->out.count = 0;
8988         *r->out.needed = 0;
8989         *r->out.info = NULL;
8990
8991         switch (r->in.level) {
8992         case 1:
8993                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8994                                                    r->out.count);
8995                 break;
8996         case 2:
8997                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8998                                                    r->out.count);
8999                 break;
9000         default:
9001                 return WERR_UNKNOWN_LEVEL;
9002         }
9003
9004         if (!W_ERROR_IS_OK(result)) {
9005                 return result;
9006         }
9007
9008         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9009                                                      spoolss_EnumMonitors,
9010                                                      *r->out.info, r->in.level,
9011                                                      *r->out.count);
9012         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9013         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9014
9015         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9016 }
9017
9018 /****************************************************************************
9019 ****************************************************************************/
9020
9021 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9022                              const print_queue_struct *queue,
9023                              int count, int snum,
9024                              struct spoolss_PrinterInfo2 *pinfo2,
9025                              uint32_t jobid,
9026                              struct spoolss_JobInfo1 *r)
9027 {
9028         int i = 0;
9029         bool found = false;
9030
9031         for (i=0; i<count; i++) {
9032                 if (queue[i].job == (int)jobid) {
9033                         found = true;
9034                         break;
9035                 }
9036         }
9037
9038         if (found == false) {
9039                 /* NT treats not found as bad param... yet another bad choice */
9040                 return WERR_INVALID_PARAM;
9041         }
9042
9043         return fill_job_info1(mem_ctx,
9044                               r,
9045                               &queue[i],
9046                               i,
9047                               snum,
9048                               pinfo2);
9049 }
9050
9051 /****************************************************************************
9052 ****************************************************************************/
9053
9054 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9055                              const print_queue_struct *queue,
9056                              int count, int snum,
9057                              struct spoolss_PrinterInfo2 *pinfo2,
9058                              uint32_t jobid,
9059                              struct spoolss_JobInfo2 *r)
9060 {
9061         int i = 0;
9062         bool found = false;
9063         struct spoolss_DeviceMode *devmode;
9064         WERROR result;
9065
9066         for (i=0; i<count; i++) {
9067                 if (queue[i].job == (int)jobid) {
9068                         found = true;
9069                         break;
9070                 }
9071         }
9072
9073         if (found == false) {
9074                 /* NT treats not found as bad param... yet another bad
9075                    choice */
9076                 return WERR_INVALID_PARAM;
9077         }
9078
9079         /*
9080          * if the print job does not have a DEVMODE associated with it,
9081          * just use the one for the printer. A NULL devicemode is not
9082          *  a failure condition
9083          */
9084
9085         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9086         if (!devmode) {
9087                 result = spoolss_create_default_devmode(mem_ctx,
9088                                                 pinfo2->printername,
9089                                                 &devmode);
9090                 if (!W_ERROR_IS_OK(result)) {
9091                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9092                         return result;
9093                 }
9094         }
9095
9096         return fill_job_info2(mem_ctx,
9097                               r,
9098                               &queue[i],
9099                               i,
9100                               snum,
9101                               pinfo2,
9102                               devmode);
9103 }
9104
9105 /****************************************************************
9106  _spoolss_GetJob
9107 ****************************************************************/
9108
9109 WERROR _spoolss_GetJob(struct pipes_struct *p,
9110                        struct spoolss_GetJob *r)
9111 {
9112         WERROR result = WERR_OK;
9113         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9114         int snum;
9115         int count;
9116         print_queue_struct      *queue = NULL;
9117         print_status_struct prt_status;
9118
9119         /* that's an [in out] buffer */
9120
9121         if (!r->in.buffer && (r->in.offered != 0)) {
9122                 return WERR_INVALID_PARAM;
9123         }
9124
9125         DEBUG(5,("_spoolss_GetJob\n"));
9126
9127         *r->out.needed = 0;
9128
9129         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9130                 return WERR_BADFID;
9131         }
9132
9133         result = winreg_get_printer(p->mem_ctx,
9134                                     get_session_info_system(),
9135                                     p->msg_ctx,
9136                                     lp_const_servicename(snum),
9137                                     &pinfo2);
9138         if (!W_ERROR_IS_OK(result)) {
9139                 return result;
9140         }
9141
9142         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9143
9144         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9145                      count, prt_status.status, prt_status.message));
9146
9147         switch (r->in.level) {
9148         case 1:
9149                 result = getjob_level_1(p->mem_ctx,
9150                                         queue, count, snum, pinfo2,
9151                                         r->in.job_id, &r->out.info->info1);
9152                 break;
9153         case 2:
9154                 result = getjob_level_2(p->mem_ctx,
9155                                         queue, count, snum, pinfo2,
9156                                         r->in.job_id, &r->out.info->info2);
9157                 break;
9158         default:
9159                 result = WERR_UNKNOWN_LEVEL;
9160                 break;
9161         }
9162
9163         SAFE_FREE(queue);
9164         TALLOC_FREE(pinfo2);
9165
9166         if (!W_ERROR_IS_OK(result)) {
9167                 TALLOC_FREE(r->out.info);
9168                 return result;
9169         }
9170
9171         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9172                                                                                    r->in.level);
9173         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9174
9175         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9176 }
9177
9178 /****************************************************************
9179  _spoolss_GetPrinterDataEx
9180 ****************************************************************/
9181
9182 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9183                                  struct spoolss_GetPrinterDataEx *r)
9184 {
9185
9186         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9187         const char *printer;
9188         int                     snum = 0;
9189         WERROR result = WERR_OK;
9190         DATA_BLOB blob;
9191         enum winreg_Type val_type;
9192         uint8_t *val_data;
9193         uint32_t val_size;
9194
9195
9196         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9197
9198         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9199                 r->in.key_name, r->in.value_name));
9200
9201         /* in case of problem, return some default values */
9202
9203         *r->out.needed  = 0;
9204         *r->out.type    = REG_NONE;
9205
9206         if (!Printer) {
9207                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9208                         OUR_HANDLE(r->in.handle)));
9209                 result = WERR_BADFID;
9210                 goto done;
9211         }
9212
9213         /* Is the handle to a printer or to the server? */
9214
9215         if (Printer->printer_type == SPLHND_SERVER) {
9216
9217                 union spoolss_PrinterData data;
9218
9219                 result = getprinterdata_printer_server(p->mem_ctx,
9220                                                        r->in.value_name,
9221                                                        r->out.type,
9222                                                        &data);
9223                 if (!W_ERROR_IS_OK(result)) {
9224                         return result;
9225                 }
9226
9227                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9228                                                   *r->out.type, &data);
9229                 if (!W_ERROR_IS_OK(result)) {
9230                         return result;
9231                 }
9232
9233                 *r->out.needed = blob.length;
9234
9235                 if (r->in.offered >= *r->out.needed) {
9236                         memcpy(r->out.data, blob.data, blob.length);
9237                 }
9238
9239                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9240         }
9241
9242         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9243                 return WERR_BADFID;
9244         }
9245         printer = lp_const_servicename(snum);
9246
9247         /* check to see if the keyname is valid */
9248         if (!strlen(r->in.key_name)) {
9249                 return WERR_INVALID_PARAM;
9250         }
9251
9252         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9253         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9254             strequal(r->in.value_name, "ChangeId")) {
9255                 *r->out.type = REG_DWORD;
9256                 *r->out.needed = 4;
9257                 if (r->in.offered >= *r->out.needed) {
9258                         uint32_t changeid = 0;
9259
9260                         result = winreg_printer_get_changeid(p->mem_ctx,
9261                                                              get_session_info_system(),
9262                                                              p->msg_ctx,
9263                                                              printer,
9264                                                              &changeid);
9265                         if (!W_ERROR_IS_OK(result)) {
9266                                 return result;
9267                         }
9268
9269                         SIVAL(r->out.data, 0, changeid);
9270                         result = WERR_OK;
9271                 }
9272                 goto done;
9273         }
9274
9275         result = winreg_get_printer_dataex(p->mem_ctx,
9276                                            get_session_info_system(),
9277                                            p->msg_ctx,
9278                                            printer,
9279                                            r->in.key_name,
9280                                            r->in.value_name,
9281                                            &val_type,
9282                                            &val_data,
9283                                            &val_size);
9284         if (!W_ERROR_IS_OK(result)) {
9285                 return result;
9286         }
9287
9288         *r->out.needed = val_size;
9289         *r->out.type = val_type;
9290
9291         if (r->in.offered >= *r->out.needed) {
9292                 memcpy(r->out.data, val_data, val_size);
9293         }
9294
9295  done:
9296         /* retain type when returning WERR_MORE_DATA */
9297         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9298
9299         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9300 }
9301
9302 /****************************************************************
9303  _spoolss_SetPrinterDataEx
9304 ****************************************************************/
9305
9306 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9307                                  struct spoolss_SetPrinterDataEx *r)
9308 {
9309         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9310         int                     snum = 0;
9311         WERROR                  result = WERR_OK;
9312         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9313         char                    *oid_string;
9314
9315         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9316
9317         /* From MSDN documentation of SetPrinterDataEx: pass request to
9318            SetPrinterData if key is "PrinterDriverData" */
9319
9320         if (!Printer) {
9321                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9322                         OUR_HANDLE(r->in.handle)));
9323                 return WERR_BADFID;
9324         }
9325
9326         if (Printer->printer_type == SPLHND_SERVER) {
9327                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9328                         "Not implemented for server handles yet\n"));
9329                 return WERR_INVALID_PARAM;
9330         }
9331
9332         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9333                 return WERR_BADFID;
9334         }
9335
9336         /*
9337          * Access check : NT returns "access denied" if you make a
9338          * SetPrinterData call without the necessary privildge.
9339          * we were originally returning OK if nothing changed
9340          * which made Win2k issue **a lot** of SetPrinterData
9341          * when connecting to a printer  --jerry
9342          */
9343
9344         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9345                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9346                         "change denied by handle access permissions\n"));
9347                 return WERR_ACCESS_DENIED;
9348         }
9349
9350         result = winreg_get_printer(Printer,
9351                                     get_session_info_system(),
9352                                     p->msg_ctx,
9353                                     lp_servicename(snum),
9354                                     &pinfo2);
9355         if (!W_ERROR_IS_OK(result)) {
9356                 return result;
9357         }
9358
9359         /* check for OID in valuename */
9360
9361         oid_string = strchr(r->in.value_name, ',');
9362         if (oid_string) {
9363                 *oid_string = '\0';
9364                 oid_string++;
9365         }
9366
9367         /* save the registry data */
9368
9369         result = winreg_set_printer_dataex(p->mem_ctx,
9370                                            get_session_info_system(),
9371                                            p->msg_ctx,
9372                                            pinfo2->sharename,
9373                                            r->in.key_name,
9374                                            r->in.value_name,
9375                                            r->in.type,
9376                                            r->in.data,
9377                                            r->in.offered);
9378
9379         if (W_ERROR_IS_OK(result)) {
9380                 /* save the OID if one was specified */
9381                 if (oid_string) {
9382                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9383                                 r->in.key_name, SPOOL_OID_KEY);
9384                         if (!str) {
9385                                 result = WERR_NOMEM;
9386                                 goto done;
9387                         }
9388
9389                         /*
9390                          * I'm not checking the status here on purpose.  Don't know
9391                          * if this is right, but I'm returning the status from the
9392                          * previous set_printer_dataex() call.  I have no idea if
9393                          * this is right.    --jerry
9394                          */
9395                         winreg_set_printer_dataex(p->mem_ctx,
9396                                                   get_session_info_system(),
9397                                                   p->msg_ctx,
9398                                                   pinfo2->sharename,
9399                                                   str,
9400                                                   r->in.value_name,
9401                                                   REG_SZ,
9402                                                   (uint8_t *) oid_string,
9403                                                   strlen(oid_string) + 1);
9404                 }
9405
9406                 result = winreg_printer_update_changeid(p->mem_ctx,
9407                                                         get_session_info_system(),
9408                                                         p->msg_ctx,
9409                                                         lp_const_servicename(snum));
9410
9411         }
9412
9413 done:
9414         talloc_free(pinfo2);
9415         return result;
9416 }
9417
9418 /****************************************************************
9419  _spoolss_DeletePrinterDataEx
9420 ****************************************************************/
9421
9422 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9423                                     struct spoolss_DeletePrinterDataEx *r)
9424 {
9425         const char *printer;
9426         int             snum=0;
9427         WERROR          status = WERR_OK;
9428         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9429
9430         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9431
9432         if (!Printer) {
9433                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9434                         "Invalid handle (%s:%u:%u).\n",
9435                         OUR_HANDLE(r->in.handle)));
9436                 return WERR_BADFID;
9437         }
9438
9439         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9440                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9441                         "printer properties change denied by handle\n"));
9442                 return WERR_ACCESS_DENIED;
9443         }
9444
9445         if (!r->in.value_name || !r->in.key_name) {
9446                 return WERR_NOMEM;
9447         }
9448
9449         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9450                 return WERR_BADFID;
9451         }
9452         printer = lp_const_servicename(snum);
9453
9454         status = winreg_delete_printer_dataex(p->mem_ctx,
9455                                               get_session_info_system(),
9456                                               p->msg_ctx,
9457                                               printer,
9458                                               r->in.key_name,
9459                                               r->in.value_name);
9460         if (W_ERROR_IS_OK(status)) {
9461                 status = winreg_printer_update_changeid(p->mem_ctx,
9462                                                         get_session_info_system(),
9463                                                         p->msg_ctx,
9464                                                         printer);
9465         }
9466
9467         return status;
9468 }
9469
9470 /****************************************************************
9471  _spoolss_EnumPrinterKey
9472 ****************************************************************/
9473
9474 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9475                                struct spoolss_EnumPrinterKey *r)
9476 {
9477         uint32_t        num_keys;
9478         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9479         int             snum = 0;
9480         WERROR          result = WERR_BADFILE;
9481         const char **array = NULL;
9482         DATA_BLOB blob;
9483
9484         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9485
9486         if (!Printer) {
9487                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9488                         OUR_HANDLE(r->in.handle)));
9489                 return WERR_BADFID;
9490         }
9491
9492         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9493                 return WERR_BADFID;
9494         }
9495
9496         result = winreg_enum_printer_key(p->mem_ctx,
9497                                          get_session_info_system(),
9498                                          p->msg_ctx,
9499                                          lp_const_servicename(snum),
9500                                          r->in.key_name,
9501                                          &num_keys,
9502                                          &array);
9503         if (!W_ERROR_IS_OK(result)) {
9504                 goto done;
9505         }
9506
9507         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9508                 result = WERR_NOMEM;
9509                 goto done;
9510         }
9511
9512         *r->out._ndr_size = r->in.offered / 2;
9513         *r->out.needed = blob.length;
9514
9515         if (r->in.offered < *r->out.needed) {
9516                 result = WERR_MORE_DATA;
9517         } else {
9518                 result = WERR_OK;
9519                 r->out.key_buffer->string_array = array;
9520         }
9521
9522  done:
9523         if (!W_ERROR_IS_OK(result)) {
9524                 TALLOC_FREE(array);
9525                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9526                         *r->out.needed = 0;
9527                 }
9528         }
9529
9530         return result;
9531 }
9532
9533 /****************************************************************
9534  _spoolss_DeletePrinterKey
9535 ****************************************************************/
9536
9537 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9538                                  struct spoolss_DeletePrinterKey *r)
9539 {
9540         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9541         int                     snum=0;
9542         WERROR                  status;
9543         const char *printer;
9544
9545         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9546
9547         if (!Printer) {
9548                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9549                         OUR_HANDLE(r->in.handle)));
9550                 return WERR_BADFID;
9551         }
9552
9553         /* if keyname == NULL, return error */
9554         if ( !r->in.key_name )
9555                 return WERR_INVALID_PARAM;
9556
9557         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9558                 return WERR_BADFID;
9559         }
9560
9561         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9562                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9563                         "printer properties change denied by handle\n"));
9564                 return WERR_ACCESS_DENIED;
9565         }
9566
9567         printer = lp_const_servicename(snum);
9568
9569         /* delete the key and all subkeys */
9570         status = winreg_delete_printer_key(p->mem_ctx,
9571                                            get_session_info_system(),
9572                                            p->msg_ctx,
9573                                            printer,
9574                                            r->in.key_name);
9575         if (W_ERROR_IS_OK(status)) {
9576                 status = winreg_printer_update_changeid(p->mem_ctx,
9577                                                         get_session_info_system(),
9578                                                         p->msg_ctx,
9579                                                         printer);
9580         }
9581
9582         return status;
9583 }
9584
9585 /****************************************************************
9586  _spoolss_EnumPrinterDataEx
9587 ****************************************************************/
9588
9589 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9590                                   struct spoolss_EnumPrinterDataEx *r)
9591 {
9592         uint32_t        count = 0;
9593         struct spoolss_PrinterEnumValues *info = NULL;
9594         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9595         int             snum;
9596         WERROR          result;
9597
9598         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9599
9600         *r->out.count = 0;
9601         *r->out.needed = 0;
9602         *r->out.info = NULL;
9603
9604         if (!Printer) {
9605                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9606                         OUR_HANDLE(r->in.handle)));
9607                 return WERR_BADFID;
9608         }
9609
9610         /*
9611          * first check for a keyname of NULL or "".  Win2k seems to send
9612          * this a lot and we should send back WERR_INVALID_PARAM
9613          * no need to spend time looking up the printer in this case.
9614          * --jerry
9615          */
9616
9617         if (!strlen(r->in.key_name)) {
9618                 result = WERR_INVALID_PARAM;
9619                 goto done;
9620         }
9621
9622         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9623                 return WERR_BADFID;
9624         }
9625
9626         /* now look for a match on the key name */
9627         result = winreg_enum_printer_dataex(p->mem_ctx,
9628                                             get_session_info_system(),
9629                                             p->msg_ctx,
9630                                             lp_const_servicename(snum),
9631                                             r->in.key_name,
9632                                             &count,
9633                                             &info);
9634         if (!W_ERROR_IS_OK(result)) {
9635                 goto done;
9636         }
9637
9638 #if 0 /* FIXME - gd */
9639         /* housekeeping information in the reply */
9640
9641         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9642          * the hand marshalled container size is a multiple
9643          * of 4 bytes for RPC alignment.
9644          */
9645
9646         if (needed % 4) {
9647                 needed += 4-(needed % 4);
9648         }
9649 #endif
9650         *r->out.count   = count;
9651         *r->out.info    = info;
9652
9653  done:
9654         if (!W_ERROR_IS_OK(result)) {
9655                 return result;
9656         }
9657
9658         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9659                                                spoolss_EnumPrinterDataEx,
9660                                                *r->out.info,
9661                                                *r->out.count);
9662         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9663         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9664
9665         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9666 }
9667
9668 /****************************************************************************
9669 ****************************************************************************/
9670
9671 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9672                                                  const char *servername,
9673                                                  const char *environment,
9674                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9675 {
9676         WERROR werr;
9677         char *path = NULL;
9678
9679         werr = compose_spoolss_server_path(mem_ctx,
9680                                            servername,
9681                                            environment,
9682                                            SPOOLSS_PRTPROCS_PATH,
9683                                            &path);
9684         if (!W_ERROR_IS_OK(werr)) {
9685                 return werr;
9686         }
9687
9688         DEBUG(4,("print processor directory: [%s]\n", path));
9689
9690         r->directory_name = path;
9691
9692         return WERR_OK;
9693 }
9694
9695 /****************************************************************
9696  _spoolss_GetPrintProcessorDirectory
9697 ****************************************************************/
9698
9699 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9700                                            struct spoolss_GetPrintProcessorDirectory *r)
9701 {
9702         WERROR result;
9703         char *prnproc_share = NULL;
9704         bool prnproc_share_exists = false;
9705         int snum;
9706
9707         /* that's an [in out] buffer */
9708
9709         if (!r->in.buffer && (r->in.offered != 0)) {
9710                 return WERR_INVALID_PARAM;
9711         }
9712
9713         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9714                 r->in.level));
9715
9716         *r->out.needed = 0;
9717
9718         /* r->in.level is ignored */
9719
9720         /* We always should reply with a local print processor directory so that
9721          * users are not forced to have a [prnproc$] share on the Samba spoolss
9722          * server, if users decide to do so, lets announce it though - Guenther */
9723
9724         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9725         if (!prnproc_share) {
9726                 return WERR_NOMEM;
9727         }
9728         if (snum != -1) {
9729                 prnproc_share_exists = true;
9730         }
9731
9732         result = getprintprocessordirectory_level_1(p->mem_ctx,
9733                                                     prnproc_share_exists ? r->in.server : NULL,
9734                                                     r->in.environment,
9735                                                     &r->out.info->info1);
9736         if (!W_ERROR_IS_OK(result)) {
9737                 TALLOC_FREE(r->out.info);
9738                 return result;
9739         }
9740
9741         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9742                                                                                    r->out.info, r->in.level);
9743         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9744
9745         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9746 }
9747
9748 /*******************************************************************
9749  ********************************************************************/
9750
9751 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9752                                const char *dllname)
9753 {
9754         enum ndr_err_code ndr_err;
9755         struct spoolss_MonitorUi ui;
9756
9757         ui.dll_name = dllname;
9758
9759         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9760                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9761         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9762                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9763         }
9764         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9765 }
9766
9767 /*******************************************************************
9768  Streams the monitor UI DLL name in UNICODE
9769 *******************************************************************/
9770
9771 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9772                                struct security_token *token, DATA_BLOB *in,
9773                                DATA_BLOB *out, uint32_t *needed)
9774 {
9775         const char *dllname = "tcpmonui.dll";
9776
9777         *needed = (strlen(dllname)+1) * 2;
9778
9779         if (out->length < *needed) {
9780                 return WERR_INSUFFICIENT_BUFFER;
9781         }
9782
9783         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9784                 return WERR_NOMEM;
9785         }
9786
9787         return WERR_OK;
9788 }
9789
9790 /*******************************************************************
9791  ********************************************************************/
9792
9793 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9794                              struct spoolss_PortData1 *port1,
9795                              const DATA_BLOB *buf)
9796 {
9797         enum ndr_err_code ndr_err;
9798         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9799                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9800         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9801                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9802         }
9803         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9804 }
9805
9806 /*******************************************************************
9807  ********************************************************************/
9808
9809 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9810                              struct spoolss_PortData2 *port2,
9811                              const DATA_BLOB *buf)
9812 {
9813         enum ndr_err_code ndr_err;
9814         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9815                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9816         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9817                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9818         }
9819         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9820 }
9821
9822 /*******************************************************************
9823  Create a new TCP/IP port
9824 *******************************************************************/
9825
9826 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9827                              struct security_token *token, DATA_BLOB *in,
9828                              DATA_BLOB *out, uint32_t *needed)
9829 {
9830         struct spoolss_PortData1 port1;
9831         struct spoolss_PortData2 port2;
9832         char *device_uri = NULL;
9833         uint32_t version;
9834
9835         const char *portname;
9836         const char *hostaddress;
9837         const char *queue;
9838         uint32_t port_number;
9839         uint32_t protocol;
9840
9841         /* peek for spoolss_PortData version */
9842
9843         if (!in || (in->length < (128 + 4))) {
9844                 return WERR_GENERAL_FAILURE;
9845         }
9846
9847         version = IVAL(in->data, 128);
9848
9849         switch (version) {
9850                 case 1:
9851                         ZERO_STRUCT(port1);
9852
9853                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9854                                 return WERR_NOMEM;
9855                         }
9856
9857                         portname        = port1.portname;
9858                         hostaddress     = port1.hostaddress;
9859                         queue           = port1.queue;
9860                         protocol        = port1.protocol;
9861                         port_number     = port1.port_number;
9862
9863                         break;
9864                 case 2:
9865                         ZERO_STRUCT(port2);
9866
9867                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9868                                 return WERR_NOMEM;
9869                         }
9870
9871                         portname        = port2.portname;
9872                         hostaddress     = port2.hostaddress;
9873                         queue           = port2.queue;
9874                         protocol        = port2.protocol;
9875                         port_number     = port2.port_number;
9876
9877                         break;
9878                 default:
9879                         DEBUG(1,("xcvtcp_addport: "
9880                                 "unknown version of port_data: %d\n", version));
9881                         return WERR_UNKNOWN_PORT;
9882         }
9883
9884         /* create the device URI and call the add_port_hook() */
9885
9886         switch (protocol) {
9887         case PROTOCOL_RAWTCP_TYPE:
9888                 device_uri = talloc_asprintf(mem_ctx,
9889                                 "socket://%s:%d/", hostaddress,
9890                                 port_number);
9891                 break;
9892
9893         case PROTOCOL_LPR_TYPE:
9894                 device_uri = talloc_asprintf(mem_ctx,
9895                         "lpr://%s/%s", hostaddress, queue );
9896                 break;
9897
9898         default:
9899                 return WERR_UNKNOWN_PORT;
9900         }
9901
9902         if (!device_uri) {
9903                 return WERR_NOMEM;
9904         }
9905
9906         return add_port_hook(mem_ctx, token, portname, device_uri);
9907 }
9908
9909 /*******************************************************************
9910 *******************************************************************/
9911
9912 struct xcv_api_table xcvtcp_cmds[] = {
9913         { "MonitorUI",  xcvtcp_monitorui },
9914         { "AddPort",    xcvtcp_addport},
9915         { NULL,         NULL }
9916 };
9917
9918 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9919                                      struct security_token *token, const char *command,
9920                                      DATA_BLOB *inbuf,
9921                                      DATA_BLOB *outbuf,
9922                                      uint32_t *needed )
9923 {
9924         int i;
9925
9926         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9927
9928         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9929                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9930                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9931         }
9932
9933         return WERR_BADFUNC;
9934 }
9935
9936 /*******************************************************************
9937 *******************************************************************/
9938 #if 0   /* don't support management using the "Local Port" monitor */
9939
9940 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9941                                  struct security_token *token, DATA_BLOB *in,
9942                                  DATA_BLOB *out, uint32_t *needed)
9943 {
9944         const char *dllname = "localui.dll";
9945
9946         *needed = (strlen(dllname)+1) * 2;
9947
9948         if (out->length < *needed) {
9949                 return WERR_INSUFFICIENT_BUFFER;
9950         }
9951
9952         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9953                 return WERR_NOMEM;
9954         }
9955
9956         return WERR_OK;
9957 }
9958
9959 /*******************************************************************
9960 *******************************************************************/
9961
9962 struct xcv_api_table xcvlocal_cmds[] = {
9963         { "MonitorUI",  xcvlocal_monitorui },
9964         { NULL,         NULL }
9965 };
9966 #else
9967 struct xcv_api_table xcvlocal_cmds[] = {
9968         { NULL,         NULL }
9969 };
9970 #endif
9971
9972
9973
9974 /*******************************************************************
9975 *******************************************************************/
9976
9977 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9978                                        struct security_token *token, const char *command,
9979                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9980                                        uint32_t *needed)
9981 {
9982         int i;
9983
9984         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9985
9986         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9987                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9988                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9989         }
9990         return WERR_BADFUNC;
9991 }
9992
9993 /****************************************************************
9994  _spoolss_XcvData
9995 ****************************************************************/
9996
9997 WERROR _spoolss_XcvData(struct pipes_struct *p,
9998                         struct spoolss_XcvData *r)
9999 {
10000         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10001         DATA_BLOB out_data = data_blob_null;
10002         WERROR werror;
10003
10004         if (!Printer) {
10005                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10006                         OUR_HANDLE(r->in.handle)));
10007                 return WERR_BADFID;
10008         }
10009
10010         /* Has to be a handle to the TCP/IP port monitor */
10011
10012         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10013                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10014                 return WERR_BADFID;
10015         }
10016
10017         /* requires administrative access to the server */
10018
10019         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10020                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10021                 return WERR_ACCESS_DENIED;
10022         }
10023
10024         /* Allocate the outgoing buffer */
10025
10026         if (r->in.out_data_size) {
10027                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10028                 if (out_data.data == NULL) {
10029                         return WERR_NOMEM;
10030                 }
10031         }
10032
10033         switch ( Printer->printer_type ) {
10034         case SPLHND_PORTMON_TCP:
10035                 werror = process_xcvtcp_command(p->mem_ctx,
10036                                                 p->session_info->security_token,
10037                                                 r->in.function_name,
10038                                                 &r->in.in_data, &out_data,
10039                                                 r->out.needed);
10040                 break;
10041         case SPLHND_PORTMON_LOCAL:
10042                 werror = process_xcvlocal_command(p->mem_ctx,
10043                                                   p->session_info->security_token,
10044                                                   r->in.function_name,
10045                                                   &r->in.in_data, &out_data,
10046                                                   r->out.needed);
10047                 break;
10048         default:
10049                 werror = WERR_INVALID_PRINT_MONITOR;
10050         }
10051
10052         if (!W_ERROR_IS_OK(werror)) {
10053                 return werror;
10054         }
10055
10056         *r->out.status_code = 0;
10057
10058         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10059                 memcpy(r->out.out_data, out_data.data,
10060                         MIN(r->in.out_data_size, out_data.length));
10061         }
10062
10063         return WERR_OK;
10064 }
10065
10066 /****************************************************************
10067  _spoolss_AddPrintProcessor
10068 ****************************************************************/
10069
10070 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10071                                   struct spoolss_AddPrintProcessor *r)
10072 {
10073         /* for now, just indicate success and ignore the add.  We'll
10074            automatically set the winprint processor for printer
10075            entries later.  Used to debug the LexMark Optra S 1855 PCL
10076            driver --jerry */
10077
10078         return WERR_OK;
10079 }
10080
10081 /****************************************************************
10082  _spoolss_AddPort
10083 ****************************************************************/
10084
10085 WERROR _spoolss_AddPort(struct pipes_struct *p,
10086                         struct spoolss_AddPort *r)
10087 {
10088         /* do what w2k3 does */
10089
10090         return WERR_NOT_SUPPORTED;
10091 }
10092
10093 /****************************************************************
10094  _spoolss_GetPrinterDriver
10095 ****************************************************************/
10096
10097 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10098                                  struct spoolss_GetPrinterDriver *r)
10099 {
10100         p->rng_fault_state = true;
10101         return WERR_NOT_SUPPORTED;
10102 }
10103
10104 /****************************************************************
10105  _spoolss_ReadPrinter
10106 ****************************************************************/
10107
10108 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10109                             struct spoolss_ReadPrinter *r)
10110 {
10111         p->rng_fault_state = true;
10112         return WERR_NOT_SUPPORTED;
10113 }
10114
10115 /****************************************************************
10116  _spoolss_WaitForPrinterChange
10117 ****************************************************************/
10118
10119 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10120                                      struct spoolss_WaitForPrinterChange *r)
10121 {
10122         p->rng_fault_state = true;
10123         return WERR_NOT_SUPPORTED;
10124 }
10125
10126 /****************************************************************
10127  _spoolss_ConfigurePort
10128 ****************************************************************/
10129
10130 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10131                               struct spoolss_ConfigurePort *r)
10132 {
10133         p->rng_fault_state = true;
10134         return WERR_NOT_SUPPORTED;
10135 }
10136
10137 /****************************************************************
10138  _spoolss_DeletePort
10139 ****************************************************************/
10140
10141 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10142                            struct spoolss_DeletePort *r)
10143 {
10144         p->rng_fault_state = true;
10145         return WERR_NOT_SUPPORTED;
10146 }
10147
10148 /****************************************************************
10149  _spoolss_CreatePrinterIC
10150 ****************************************************************/
10151
10152 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10153                                 struct spoolss_CreatePrinterIC *r)
10154 {
10155         p->rng_fault_state = true;
10156         return WERR_NOT_SUPPORTED;
10157 }
10158
10159 /****************************************************************
10160  _spoolss_PlayGDIScriptOnPrinterIC
10161 ****************************************************************/
10162
10163 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10164                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10165 {
10166         p->rng_fault_state = true;
10167         return WERR_NOT_SUPPORTED;
10168 }
10169
10170 /****************************************************************
10171  _spoolss_DeletePrinterIC
10172 ****************************************************************/
10173
10174 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10175                                 struct spoolss_DeletePrinterIC *r)
10176 {
10177         p->rng_fault_state = true;
10178         return WERR_NOT_SUPPORTED;
10179 }
10180
10181 /****************************************************************
10182  _spoolss_AddPrinterConnection
10183 ****************************************************************/
10184
10185 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10186                                      struct spoolss_AddPrinterConnection *r)
10187 {
10188         p->rng_fault_state = true;
10189         return WERR_NOT_SUPPORTED;
10190 }
10191
10192 /****************************************************************
10193  _spoolss_DeletePrinterConnection
10194 ****************************************************************/
10195
10196 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10197                                         struct spoolss_DeletePrinterConnection *r)
10198 {
10199         p->rng_fault_state = true;
10200         return WERR_NOT_SUPPORTED;
10201 }
10202
10203 /****************************************************************
10204  _spoolss_PrinterMessageBox
10205 ****************************************************************/
10206
10207 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10208                                   struct spoolss_PrinterMessageBox *r)
10209 {
10210         p->rng_fault_state = true;
10211         return WERR_NOT_SUPPORTED;
10212 }
10213
10214 /****************************************************************
10215  _spoolss_AddMonitor
10216 ****************************************************************/
10217
10218 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10219                            struct spoolss_AddMonitor *r)
10220 {
10221         p->rng_fault_state = true;
10222         return WERR_NOT_SUPPORTED;
10223 }
10224
10225 /****************************************************************
10226  _spoolss_DeleteMonitor
10227 ****************************************************************/
10228
10229 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10230                               struct spoolss_DeleteMonitor *r)
10231 {
10232         p->rng_fault_state = true;
10233         return WERR_NOT_SUPPORTED;
10234 }
10235
10236 /****************************************************************
10237  _spoolss_DeletePrintProcessor
10238 ****************************************************************/
10239
10240 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10241                                      struct spoolss_DeletePrintProcessor *r)
10242 {
10243         p->rng_fault_state = true;
10244         return WERR_NOT_SUPPORTED;
10245 }
10246
10247 /****************************************************************
10248  _spoolss_AddPrintProvidor
10249 ****************************************************************/
10250
10251 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10252                                  struct spoolss_AddPrintProvidor *r)
10253 {
10254         p->rng_fault_state = true;
10255         return WERR_NOT_SUPPORTED;
10256 }
10257
10258 /****************************************************************
10259  _spoolss_DeletePrintProvidor
10260 ****************************************************************/
10261
10262 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10263                                     struct spoolss_DeletePrintProvidor *r)
10264 {
10265         p->rng_fault_state = true;
10266         return WERR_NOT_SUPPORTED;
10267 }
10268
10269 /****************************************************************
10270  _spoolss_FindFirstPrinterChangeNotification
10271 ****************************************************************/
10272
10273 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10274                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10275 {
10276         p->rng_fault_state = true;
10277         return WERR_NOT_SUPPORTED;
10278 }
10279
10280 /****************************************************************
10281  _spoolss_FindNextPrinterChangeNotification
10282 ****************************************************************/
10283
10284 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10285                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10286 {
10287         p->rng_fault_state = true;
10288         return WERR_NOT_SUPPORTED;
10289 }
10290
10291 /****************************************************************
10292  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10293 ****************************************************************/
10294
10295 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10296                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10297 {
10298         p->rng_fault_state = true;
10299         return WERR_NOT_SUPPORTED;
10300 }
10301
10302 /****************************************************************
10303  _spoolss_ReplyOpenPrinter
10304 ****************************************************************/
10305
10306 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10307                                  struct spoolss_ReplyOpenPrinter *r)
10308 {
10309         p->rng_fault_state = true;
10310         return WERR_NOT_SUPPORTED;
10311 }
10312
10313 /****************************************************************
10314  _spoolss_RouterReplyPrinter
10315 ****************************************************************/
10316
10317 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10318                                    struct spoolss_RouterReplyPrinter *r)
10319 {
10320         p->rng_fault_state = true;
10321         return WERR_NOT_SUPPORTED;
10322 }
10323
10324 /****************************************************************
10325  _spoolss_ReplyClosePrinter
10326 ****************************************************************/
10327
10328 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10329                                   struct spoolss_ReplyClosePrinter *r)
10330 {
10331         p->rng_fault_state = true;
10332         return WERR_NOT_SUPPORTED;
10333 }
10334
10335 /****************************************************************
10336  _spoolss_AddPortEx
10337 ****************************************************************/
10338
10339 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10340                           struct spoolss_AddPortEx *r)
10341 {
10342         p->rng_fault_state = true;
10343         return WERR_NOT_SUPPORTED;
10344 }
10345
10346 /****************************************************************
10347  _spoolss_RouterFindFirstPrinterChangeNotification
10348 ****************************************************************/
10349
10350 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10351                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10352 {
10353         p->rng_fault_state = true;
10354         return WERR_NOT_SUPPORTED;
10355 }
10356
10357 /****************************************************************
10358  _spoolss_SpoolerInit
10359 ****************************************************************/
10360
10361 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10362                             struct spoolss_SpoolerInit *r)
10363 {
10364         p->rng_fault_state = true;
10365         return WERR_NOT_SUPPORTED;
10366 }
10367
10368 /****************************************************************
10369  _spoolss_ResetPrinterEx
10370 ****************************************************************/
10371
10372 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10373                                struct spoolss_ResetPrinterEx *r)
10374 {
10375         p->rng_fault_state = true;
10376         return WERR_NOT_SUPPORTED;
10377 }
10378
10379 /****************************************************************
10380  _spoolss_RouterReplyPrinterEx
10381 ****************************************************************/
10382
10383 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10384                                      struct spoolss_RouterReplyPrinterEx *r)
10385 {
10386         p->rng_fault_state = true;
10387         return WERR_NOT_SUPPORTED;
10388 }
10389
10390 /****************************************************************
10391  _spoolss_44
10392 ****************************************************************/
10393
10394 WERROR _spoolss_44(struct pipes_struct *p,
10395                    struct spoolss_44 *r)
10396 {
10397         p->rng_fault_state = true;
10398         return WERR_NOT_SUPPORTED;
10399 }
10400
10401 /****************************************************************
10402  _spoolss_SetPort
10403 ****************************************************************/
10404
10405 WERROR _spoolss_SetPort(struct pipes_struct *p,
10406                         struct spoolss_SetPort *r)
10407 {
10408         p->rng_fault_state = true;
10409         return WERR_NOT_SUPPORTED;
10410 }
10411
10412 /****************************************************************
10413  _spoolss_4a
10414 ****************************************************************/
10415
10416 WERROR _spoolss_4a(struct pipes_struct *p,
10417                    struct spoolss_4a *r)
10418 {
10419         p->rng_fault_state = true;
10420         return WERR_NOT_SUPPORTED;
10421 }
10422
10423 /****************************************************************
10424  _spoolss_4b
10425 ****************************************************************/
10426
10427 WERROR _spoolss_4b(struct pipes_struct *p,
10428                    struct spoolss_4b *r)
10429 {
10430         p->rng_fault_state = true;
10431         return WERR_NOT_SUPPORTED;
10432 }
10433
10434 /****************************************************************
10435  _spoolss_4c
10436 ****************************************************************/
10437
10438 WERROR _spoolss_4c(struct pipes_struct *p,
10439                    struct spoolss_4c *r)
10440 {
10441         p->rng_fault_state = true;
10442         return WERR_NOT_SUPPORTED;
10443 }
10444
10445 /****************************************************************
10446  _spoolss_53
10447 ****************************************************************/
10448
10449 WERROR _spoolss_53(struct pipes_struct *p,
10450                    struct spoolss_53 *r)
10451 {
10452         p->rng_fault_state = true;
10453         return WERR_NOT_SUPPORTED;
10454 }
10455
10456 /****************************************************************
10457  _spoolss_AddPerMachineConnection
10458 ****************************************************************/
10459
10460 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10461                                         struct spoolss_AddPerMachineConnection *r)
10462 {
10463         p->rng_fault_state = true;
10464         return WERR_NOT_SUPPORTED;
10465 }
10466
10467 /****************************************************************
10468  _spoolss_DeletePerMachineConnection
10469 ****************************************************************/
10470
10471 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10472                                            struct spoolss_DeletePerMachineConnection *r)
10473 {
10474         p->rng_fault_state = true;
10475         return WERR_NOT_SUPPORTED;
10476 }
10477
10478 /****************************************************************
10479  _spoolss_EnumPerMachineConnections
10480 ****************************************************************/
10481
10482 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10483                                           struct spoolss_EnumPerMachineConnections *r)
10484 {
10485         p->rng_fault_state = true;
10486         return WERR_NOT_SUPPORTED;
10487 }
10488
10489 /****************************************************************
10490  _spoolss_5a
10491 ****************************************************************/
10492
10493 WERROR _spoolss_5a(struct pipes_struct *p,
10494                    struct spoolss_5a *r)
10495 {
10496         p->rng_fault_state = true;
10497         return WERR_NOT_SUPPORTED;
10498 }
10499
10500 /****************************************************************
10501  _spoolss_5b
10502 ****************************************************************/
10503
10504 WERROR _spoolss_5b(struct pipes_struct *p,
10505                    struct spoolss_5b *r)
10506 {
10507         p->rng_fault_state = true;
10508         return WERR_NOT_SUPPORTED;
10509 }
10510
10511 /****************************************************************
10512  _spoolss_5c
10513 ****************************************************************/
10514
10515 WERROR _spoolss_5c(struct pipes_struct *p,
10516                    struct spoolss_5c *r)
10517 {
10518         p->rng_fault_state = true;
10519         return WERR_NOT_SUPPORTED;
10520 }
10521
10522 /****************************************************************
10523  _spoolss_5d
10524 ****************************************************************/
10525
10526 WERROR _spoolss_5d(struct pipes_struct *p,
10527                    struct spoolss_5d *r)
10528 {
10529         p->rng_fault_state = true;
10530         return WERR_NOT_SUPPORTED;
10531 }
10532
10533 /****************************************************************
10534  _spoolss_5e
10535 ****************************************************************/
10536
10537 WERROR _spoolss_5e(struct pipes_struct *p,
10538                    struct spoolss_5e *r)
10539 {
10540         p->rng_fault_state = true;
10541         return WERR_NOT_SUPPORTED;
10542 }
10543
10544 /****************************************************************
10545  _spoolss_5f
10546 ****************************************************************/
10547
10548 WERROR _spoolss_5f(struct pipes_struct *p,
10549                    struct spoolss_5f *r)
10550 {
10551         p->rng_fault_state = true;
10552         return WERR_NOT_SUPPORTED;
10553 }
10554
10555 /****************************************************************
10556  _spoolss_60
10557 ****************************************************************/
10558
10559 WERROR _spoolss_60(struct pipes_struct *p,
10560                    struct spoolss_60 *r)
10561 {
10562         p->rng_fault_state = true;
10563         return WERR_NOT_SUPPORTED;
10564 }
10565
10566 /****************************************************************
10567  _spoolss_61
10568 ****************************************************************/
10569
10570 WERROR _spoolss_61(struct pipes_struct *p,
10571                    struct spoolss_61 *r)
10572 {
10573         p->rng_fault_state = true;
10574         return WERR_NOT_SUPPORTED;
10575 }
10576
10577 /****************************************************************
10578  _spoolss_62
10579 ****************************************************************/
10580
10581 WERROR _spoolss_62(struct pipes_struct *p,
10582                    struct spoolss_62 *r)
10583 {
10584         p->rng_fault_state = true;
10585         return WERR_NOT_SUPPORTED;
10586 }
10587
10588 /****************************************************************
10589  _spoolss_63
10590 ****************************************************************/
10591
10592 WERROR _spoolss_63(struct pipes_struct *p,
10593                    struct spoolss_63 *r)
10594 {
10595         p->rng_fault_state = true;
10596         return WERR_NOT_SUPPORTED;
10597 }
10598
10599 /****************************************************************
10600  _spoolss_64
10601 ****************************************************************/
10602
10603 WERROR _spoolss_64(struct pipes_struct *p,
10604                    struct spoolss_64 *r)
10605 {
10606         p->rng_fault_state = true;
10607         return WERR_NOT_SUPPORTED;
10608 }
10609
10610 /****************************************************************
10611  _spoolss_65
10612 ****************************************************************/
10613
10614 WERROR _spoolss_65(struct pipes_struct *p,
10615                    struct spoolss_65 *r)
10616 {
10617         p->rng_fault_state = true;
10618         return WERR_NOT_SUPPORTED;
10619 }
10620
10621 /****************************************************************
10622  _spoolss_GetCorePrinterDrivers
10623 ****************************************************************/
10624
10625 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10626                                       struct spoolss_GetCorePrinterDrivers *r)
10627 {
10628         p->rng_fault_state = true;
10629         return WERR_NOT_SUPPORTED;
10630 }
10631
10632 /****************************************************************
10633  _spoolss_67
10634 ****************************************************************/
10635
10636 WERROR _spoolss_67(struct pipes_struct *p,
10637                    struct spoolss_67 *r)
10638 {
10639         p->rng_fault_state = true;
10640         return WERR_NOT_SUPPORTED;
10641 }
10642
10643 /****************************************************************
10644  _spoolss_GetPrinterDriverPackagePath
10645 ****************************************************************/
10646
10647 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10648                                             struct spoolss_GetPrinterDriverPackagePath *r)
10649 {
10650         p->rng_fault_state = true;
10651         return WERR_NOT_SUPPORTED;
10652 }
10653
10654 /****************************************************************
10655  _spoolss_69
10656 ****************************************************************/
10657
10658 WERROR _spoolss_69(struct pipes_struct *p,
10659                    struct spoolss_69 *r)
10660 {
10661         p->rng_fault_state = true;
10662         return WERR_NOT_SUPPORTED;
10663 }
10664
10665 /****************************************************************
10666  _spoolss_6a
10667 ****************************************************************/
10668
10669 WERROR _spoolss_6a(struct pipes_struct *p,
10670                    struct spoolss_6a *r)
10671 {
10672         p->rng_fault_state = true;
10673         return WERR_NOT_SUPPORTED;
10674 }
10675
10676 /****************************************************************
10677  _spoolss_6b
10678 ****************************************************************/
10679
10680 WERROR _spoolss_6b(struct pipes_struct *p,
10681                    struct spoolss_6b *r)
10682 {
10683         p->rng_fault_state = true;
10684         return WERR_NOT_SUPPORTED;
10685 }
10686
10687 /****************************************************************
10688  _spoolss_6c
10689 ****************************************************************/
10690
10691 WERROR _spoolss_6c(struct pipes_struct *p,
10692                    struct spoolss_6c *r)
10693 {
10694         p->rng_fault_state = true;
10695         return WERR_NOT_SUPPORTED;
10696 }
10697
10698 /****************************************************************
10699  _spoolss_6d
10700 ****************************************************************/
10701
10702 WERROR _spoolss_6d(struct pipes_struct *p,
10703                    struct spoolss_6d *r)
10704 {
10705         p->rng_fault_state = true;
10706         return WERR_NOT_SUPPORTED;
10707 }