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