s3: only include tdb headers where needed.
[ab/samba.git/.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 "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54
55 /* macros stolen from s4 spoolss server */
56 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
57         ((info)?ndr_size_##fn(info, level, 0):0)
58
59 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
60         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
61
62 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
63         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
64
65 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
66
67 #undef DBGC_CLASS
68 #define DBGC_CLASS DBGC_RPC_SRV
69
70 #ifndef MAX_OPEN_PRINTER_EXS
71 #define MAX_OPEN_PRINTER_EXS 50
72 #endif
73
74 struct notify_back_channel;
75
76 /* structure to store the printer handles */
77 /* and a reference to what it's pointing to */
78 /* and the notify info asked about */
79 /* that's the central struct */
80 struct printer_handle {
81         struct printer_handle *prev, *next;
82         bool document_started;
83         bool page_started;
84         uint32 jobid; /* jobid in printing backend */
85         int printer_type;
86         const char *servername;
87         fstring sharename;
88         uint32 type;
89         uint32 access_granted;
90         struct {
91                 uint32 flags;
92                 uint32 options;
93                 fstring localmachine;
94                 uint32 printerlocal;
95                 struct spoolss_NotifyOption *option;
96                 struct policy_handle cli_hnd;
97                 struct notify_back_channel *cli_chan;
98                 uint32 change;
99                 /* are we in a FindNextPrinterChangeNotify() call? */
100                 bool fnpcn;
101                 struct messaging_context *msg_ctx;
102         } notify;
103         struct {
104                 fstring machine;
105                 fstring user;
106         } client;
107
108         /* devmode sent in the OpenPrinter() call */
109         struct spoolss_DeviceMode *devmode;
110
111         /* TODO cache the printer info2 structure */
112         struct spoolss_PrinterInfo2 *info2;
113
114 };
115
116 static struct printer_handle *printers_list;
117
118 struct printer_session_counter {
119         struct printer_session_counter *next;
120         struct printer_session_counter *prev;
121
122         int snum;
123         uint32_t counter;
124 };
125
126 static struct printer_session_counter *counter_list;
127
128 struct notify_back_channel {
129         struct notify_back_channel *prev, *next;
130
131         /* associated client */
132         struct sockaddr_storage client_address;
133
134         /* print notify back-channel pipe handle*/
135         struct rpc_pipe_client *cli_pipe;
136         struct dcerpc_binding_handle *binding_handle;
137         uint32_t active_connections;
138 };
139
140 static struct notify_back_channel *back_channels;
141
142 /* Map generic permissions to printer object specific permissions */
143
144 const struct standard_mapping printer_std_mapping = {
145         PRINTER_READ,
146         PRINTER_WRITE,
147         PRINTER_EXECUTE,
148         PRINTER_ALL_ACCESS
149 };
150
151 /* Map generic permissions to print server object specific permissions */
152
153 const struct standard_mapping printserver_std_mapping = {
154         SERVER_READ,
155         SERVER_WRITE,
156         SERVER_EXECUTE,
157         SERVER_ALL_ACCESS
158 };
159
160 /* API table for Xcv Monitor functions */
161
162 struct xcv_api_table {
163         const char *name;
164         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
165 };
166
167 static void prune_printername_cache(void);
168
169 /********************************************************************
170  * Canonicalize servername.
171  ********************************************************************/
172
173 static const char *canon_servername(const char *servername)
174 {
175         const char *pservername = servername;
176         while (*pservername == '\\') {
177                 pservername++;
178         }
179         return pservername;
180 }
181
182 /* translate between internal status numbers and NT status numbers */
183 static int nt_printj_status(int v)
184 {
185         switch (v) {
186         case LPQ_QUEUED:
187                 return 0;
188         case LPQ_PAUSED:
189                 return JOB_STATUS_PAUSED;
190         case LPQ_SPOOLING:
191                 return JOB_STATUS_SPOOLING;
192         case LPQ_PRINTING:
193                 return JOB_STATUS_PRINTING;
194         case LPQ_ERROR:
195                 return JOB_STATUS_ERROR;
196         case LPQ_DELETING:
197                 return JOB_STATUS_DELETING;
198         case LPQ_OFFLINE:
199                 return JOB_STATUS_OFFLINE;
200         case LPQ_PAPEROUT:
201                 return JOB_STATUS_PAPEROUT;
202         case LPQ_PRINTED:
203                 return JOB_STATUS_PRINTED;
204         case LPQ_DELETED:
205                 return JOB_STATUS_DELETED;
206         case LPQ_BLOCKED:
207                 return JOB_STATUS_BLOCKED_DEVQ;
208         case LPQ_USER_INTERVENTION:
209                 return JOB_STATUS_USER_INTERVENTION;
210         }
211         return 0;
212 }
213
214 static int nt_printq_status(int v)
215 {
216         switch (v) {
217         case LPQ_PAUSED:
218                 return PRINTER_STATUS_PAUSED;
219         case LPQ_QUEUED:
220         case LPQ_SPOOLING:
221         case LPQ_PRINTING:
222                 return 0;
223         }
224         return 0;
225 }
226
227 /***************************************************************************
228  Disconnect from the client
229 ****************************************************************************/
230
231 static void srv_spoolss_replycloseprinter(int snum,
232                                           struct printer_handle *prn_hnd)
233 {
234         WERROR result;
235         NTSTATUS status;
236
237         /*
238          * Tell the specific printing tdb we no longer want messages for this printer
239          * by deregistering our PID.
240          */
241
242         if (!print_notify_deregister_pid(snum)) {
243                 DEBUG(0, ("Failed to register our pid for printer %s\n",
244                           lp_const_servicename(snum)));
245         }
246
247         /* weird if the test succeeds !!! */
248         if (prn_hnd->notify.cli_chan == NULL ||
249             prn_hnd->notify.cli_chan->active_connections == 0) {
250                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
251                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
252                 TALLOC_FREE(prn_hnd->notify.cli_chan);
253                 return;
254         }
255
256         status = dcerpc_spoolss_ReplyClosePrinter(
257                                         prn_hnd->notify.cli_chan->binding_handle,
258                                         talloc_tos(),
259                                         &prn_hnd->notify.cli_hnd,
260                                         &result);
261         if (!NT_STATUS_IS_OK(status)) {
262                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
263                           nt_errstr(status)));
264                 result = ntstatus_to_werror(status);
265         } else if (!W_ERROR_IS_OK(result)) {
266                 DEBUG(0, ("reply_close_printer failed [%s].\n",
267                           win_errstr(result)));
268         }
269
270         /* if it's the last connection, deconnect the IPC$ share */
271         if (prn_hnd->notify.cli_chan->active_connections == 1) {
272
273                 prn_hnd->notify.cli_chan->binding_handle = NULL;
274                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
275                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
276                 TALLOC_FREE(prn_hnd->notify.cli_chan);
277
278                 if (prn_hnd->notify.msg_ctx != NULL) {
279                         messaging_deregister(prn_hnd->notify.msg_ctx,
280                                              MSG_PRINTER_NOTIFY2, NULL);
281
282                         /*
283                          * Tell the serverid.tdb we're no longer
284                          * interested in printer notify messages.
285                          */
286
287                         serverid_register_msg_flags(
288                                 messaging_server_id(prn_hnd->notify.msg_ctx),
289                                 false, FLAG_MSG_PRINT_NOTIFY);
290                 }
291         }
292
293         if (prn_hnd->notify.cli_chan) {
294                 prn_hnd->notify.cli_chan->active_connections--;
295         }
296 }
297
298 /****************************************************************************
299  Functions to free a printer entry datastruct.
300 ****************************************************************************/
301
302 static int printer_entry_destructor(struct printer_handle *Printer)
303 {
304         if (Printer->notify.cli_chan != NULL &&
305             Printer->notify.cli_chan->active_connections > 0) {
306                 int snum = -1;
307
308                 switch(Printer->printer_type) {
309                 case SPLHND_SERVER:
310                         srv_spoolss_replycloseprinter(snum, Printer);
311                         break;
312
313                 case SPLHND_PRINTER:
314                         snum = print_queue_snum(Printer->sharename);
315                         if (snum != -1) {
316                                 srv_spoolss_replycloseprinter(snum, Printer);
317                         }
318                         break;
319                 default:
320                         break;
321                 }
322         }
323
324         Printer->notify.flags=0;
325         Printer->notify.options=0;
326         Printer->notify.localmachine[0]='\0';
327         Printer->notify.printerlocal=0;
328         TALLOC_FREE(Printer->notify.option);
329         TALLOC_FREE(Printer->devmode);
330
331         /* Remove from the internal list. */
332         DLIST_REMOVE(printers_list, Printer);
333         return 0;
334 }
335
336 /****************************************************************************
337   find printer index by handle
338 ****************************************************************************/
339
340 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
341                                                         struct policy_handle *hnd)
342 {
343         struct printer_handle *find_printer = NULL;
344
345         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
346                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
347                 return NULL;
348         }
349
350         return find_printer;
351 }
352
353 /****************************************************************************
354  Close printer index by handle.
355 ****************************************************************************/
356
357 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
358 {
359         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
360
361         if (!Printer) {
362                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
363                         OUR_HANDLE(hnd)));
364                 return false;
365         }
366
367         close_policy_hnd(p, hnd);
368
369         return true;
370 }
371
372 /****************************************************************************
373  Delete a printer given a handle.
374 ****************************************************************************/
375
376 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
377                                   const char *sharename,
378                                   struct messaging_context *msg_ctx)
379 {
380         char *cmd = lp_deleteprinter_cmd();
381         char *command = NULL;
382         int ret;
383         bool is_print_op = false;
384
385         /* can't fail if we don't try */
386
387         if ( !*cmd )
388                 return WERR_OK;
389
390         command = talloc_asprintf(ctx,
391                         "%s \"%s\"",
392                         cmd, sharename);
393         if (!command) {
394                 return WERR_NOMEM;
395         }
396         if ( token )
397                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
398
399         DEBUG(10,("Running [%s]\n", command));
400
401         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
402
403         if ( is_print_op )
404                 become_root();
405
406         if ( (ret = smbrun(command, NULL)) == 0 ) {
407                 /* Tell everyone we updated smb.conf. */
408                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
409         }
410
411         if ( is_print_op )
412                 unbecome_root();
413
414         /********** END SePrintOperatorPrivlege BLOCK **********/
415
416         DEBUGADD(10,("returned [%d]\n", ret));
417
418         TALLOC_FREE(command);
419
420         if (ret != 0)
421                 return WERR_BADFID; /* What to return here? */
422
423         /* go ahead and re-read the services immediately */
424         become_root();
425         reload_services(msg_ctx, -1, false);
426         unbecome_root();
427
428         if ( lp_servicenumber( sharename ) >= 0 )
429                 return WERR_ACCESS_DENIED;
430
431         return WERR_OK;
432 }
433
434 /****************************************************************************
435  Delete a printer given a handle.
436 ****************************************************************************/
437
438 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
439 {
440         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
441         WERROR result;
442
443         if (!Printer) {
444                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
445                         OUR_HANDLE(hnd)));
446                 return WERR_BADFID;
447         }
448
449         /*
450          * It turns out that Windows allows delete printer on a handle
451          * opened by an admin user, then used on a pipe handle created
452          * by an anonymous user..... but they're working on security.... riiight !
453          * JRA.
454          */
455
456         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
457                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
458                 return WERR_ACCESS_DENIED;
459         }
460
461         /* this does not need a become root since the access check has been
462            done on the handle already */
463
464         result = winreg_delete_printer_key(p->mem_ctx,
465                                            get_session_info_system(),
466                                            p->msg_ctx,
467                                            Printer->sharename,
468                                            "");
469         if (!W_ERROR_IS_OK(result)) {
470                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
471                 return WERR_BADFID;
472         }
473
474         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
475                                      Printer->sharename, p->msg_ctx);
476         if (!W_ERROR_IS_OK(result)) {
477                 return result;
478         }
479         prune_printername_cache();
480         return WERR_OK;
481 }
482
483 /****************************************************************************
484  Return the snum of a printer corresponding to an handle.
485 ****************************************************************************/
486
487 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
488                              int *number, struct share_params **params)
489 {
490         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
491
492         if (!Printer) {
493                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
494                         OUR_HANDLE(hnd)));
495                 return false;
496         }
497
498         switch (Printer->printer_type) {
499                 case SPLHND_PRINTER:
500                         DEBUG(4,("short name:%s\n", Printer->sharename));
501                         *number = print_queue_snum(Printer->sharename);
502                         return (*number != -1);
503                 case SPLHND_SERVER:
504                         return false;
505                 default:
506                         return false;
507         }
508 }
509
510 /****************************************************************************
511  Set printer handle type.
512  Check if it's \\server or \\server\printer
513 ****************************************************************************/
514
515 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
516 {
517         DEBUG(3,("Setting printer type=%s\n", handlename));
518
519         /* it's a print server */
520         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
521                 DEBUGADD(4,("Printer is a print server\n"));
522                 Printer->printer_type = SPLHND_SERVER;
523         }
524         /* it's a printer (set_printer_hnd_name() will handle port monitors */
525         else {
526                 DEBUGADD(4,("Printer is a printer\n"));
527                 Printer->printer_type = SPLHND_PRINTER;
528         }
529
530         return true;
531 }
532
533 static void prune_printername_cache_fn(const char *key, const char *value,
534                                        time_t timeout, void *private_data)
535 {
536         gencache_del(key);
537 }
538
539 static void prune_printername_cache(void)
540 {
541         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
542 }
543
544 /****************************************************************************
545  Set printer handle name..  Accept names like \\server, \\server\printer,
546  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
547  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
548  XcvDataPort() interface.
549 ****************************************************************************/
550
551 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
552                                    const struct auth_serversupplied_info *session_info,
553                                    struct messaging_context *msg_ctx,
554                                    struct printer_handle *Printer,
555                                    const char *handlename)
556 {
557         int snum;
558         int n_services=lp_numservices();
559         char *aprinter;
560         const char *printername;
561         const char *servername = NULL;
562         fstring sname;
563         bool found = false;
564         struct spoolss_PrinterInfo2 *info2 = NULL;
565         WERROR result;
566         char *p;
567
568         /*
569          * Hopefully nobody names his printers like this. Maybe \ or ,
570          * are illegal in printer names even?
571          */
572         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
573         char *cache_key;
574         char *tmp;
575
576         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
577                 (unsigned long)strlen(handlename)));
578
579         aprinter = discard_const_p(char, handlename);
580         if ( *handlename == '\\' ) {
581                 servername = canon_servername(handlename);
582                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
583                         *aprinter = '\0';
584                         aprinter++;
585                 }
586                 if (!is_myname_or_ipaddr(servername)) {
587                         return WERR_INVALID_PRINTER_NAME;
588                 }
589                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
590                 if (Printer->servername == NULL) {
591                         return WERR_NOMEM;
592                 }
593         }
594
595         if (Printer->printer_type == SPLHND_SERVER) {
596                 return WERR_OK;
597         }
598
599         if (Printer->printer_type != SPLHND_PRINTER) {
600                 return WERR_INVALID_HANDLE;
601         }
602
603         DEBUGADD(5, ("searching for [%s]\n", aprinter));
604
605         p = strchr(aprinter, ',');
606         if (p != NULL) {
607                 char *p2 = p;
608                 p++;
609                 if (*p == ' ') {
610                         p++;
611                 }
612                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
613                         *p2 = '\0';
614                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
615                         *p2 = '\0';
616                 }
617         }
618
619         if (p) {
620                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
621         }
622
623         /* check for the Port Monitor Interface */
624         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
625                 Printer->printer_type = SPLHND_PORTMON_TCP;
626                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
627                 found = true;
628         }
629         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
630                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
631                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
632                 found = true;
633         }
634
635         /*
636          * With hundreds of printers, the "for" loop iterating all
637          * shares can be quite expensive, as it is done on every
638          * OpenPrinter. The loop maps "aprinter" to "sname", the
639          * result of which we cache in gencache.
640          */
641
642         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
643                                     aprinter);
644         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
645
646                 found = (strcmp(tmp, printer_not_found) != 0);
647                 if (!found) {
648                         DEBUG(4, ("Printer %s not found\n", aprinter));
649                         SAFE_FREE(tmp);
650                         return WERR_INVALID_PRINTER_NAME;
651                 }
652                 fstrcpy(sname, tmp);
653                 SAFE_FREE(tmp);
654         }
655
656         /* Search all sharenames first as this is easier than pulling
657            the printer_info_2 off of disk. Don't use find_service() since
658            that calls out to map_username() */
659
660         /* do another loop to look for printernames */
661         for (snum = 0; !found && snum < n_services; snum++) {
662                 const char *printer = lp_const_servicename(snum);
663
664                 /* no point going on if this is not a printer */
665                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
666                         continue;
667                 }
668
669                 /* ignore [printers] share */
670                 if (strequal(printer, "printers")) {
671                         continue;
672                 }
673
674                 fstrcpy(sname, printer);
675                 if (strequal(aprinter, printer)) {
676                         found = true;
677                         break;
678                 }
679
680                 /* no point looking up the printer object if
681                    we aren't allowing printername != sharename */
682                 if (lp_force_printername(snum)) {
683                         continue;
684                 }
685
686                 result = winreg_get_printer(mem_ctx,
687                                             session_info,
688                                             msg_ctx,
689                                             sname,
690                                             &info2);
691                 if ( !W_ERROR_IS_OK(result) ) {
692                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
693                                  sname, win_errstr(result)));
694                         continue;
695                 }
696
697                 printername = strrchr(info2->printername, '\\');
698                 if (printername == NULL) {
699                         printername = info2->printername;
700                 } else {
701                         printername++;
702                 }
703
704                 if (strequal(printername, aprinter)) {
705                         found = true;
706                         break;
707                 }
708
709                 DEBUGADD(10, ("printername: %s\n", printername));
710
711                 TALLOC_FREE(info2);
712         }
713
714         if ( !found ) {
715                 if (cache_key != NULL) {
716                         gencache_set(cache_key, printer_not_found,
717                                      time(NULL)+300);
718                         TALLOC_FREE(cache_key);
719                 }
720                 DEBUGADD(4,("Printer not found\n"));
721                 return WERR_INVALID_PRINTER_NAME;
722         }
723
724         if (cache_key != NULL) {
725                 gencache_set(cache_key, sname, time(NULL)+300);
726                 TALLOC_FREE(cache_key);
727         }
728
729         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
730
731         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
732
733         return WERR_OK;
734 }
735
736 /****************************************************************************
737  Find first available printer slot. creates a printer handle for you.
738  ****************************************************************************/
739
740 static WERROR open_printer_hnd(struct pipes_struct *p,
741                                struct policy_handle *hnd,
742                                const char *name,
743                                uint32_t access_granted)
744 {
745         struct printer_handle *new_printer;
746         WERROR result;
747
748         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
749
750         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
751         if (new_printer == NULL) {
752                 return WERR_NOMEM;
753         }
754         talloc_set_destructor(new_printer, printer_entry_destructor);
755
756         /* This also steals the printer_handle on the policy_handle */
757         if (!create_policy_hnd(p, hnd, new_printer)) {
758                 TALLOC_FREE(new_printer);
759                 return WERR_INVALID_HANDLE;
760         }
761
762         /* Add to the internal list. */
763         DLIST_ADD(printers_list, new_printer);
764
765         new_printer->notify.option=NULL;
766
767         if (!set_printer_hnd_printertype(new_printer, name)) {
768                 close_printer_handle(p, hnd);
769                 return WERR_INVALID_HANDLE;
770         }
771
772         result = set_printer_hnd_name(p->mem_ctx,
773                                       get_session_info_system(),
774                                       p->msg_ctx,
775                                       new_printer, name);
776         if (!W_ERROR_IS_OK(result)) {
777                 close_printer_handle(p, hnd);
778                 return result;
779         }
780
781         new_printer->access_granted = access_granted;
782
783         DEBUG(5, ("%d printer handles active\n",
784                   (int)num_pipe_handles(p)));
785
786         return WERR_OK;
787 }
788
789 /***************************************************************************
790  check to see if the client motify handle is monitoring the notification
791  given by (notify_type, notify_field).
792  **************************************************************************/
793
794 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
795                                       uint16_t notify_field)
796 {
797         return true;
798 }
799
800 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
801                                 uint16_t notify_field)
802 {
803         struct spoolss_NotifyOption *option = p->notify.option;
804         uint32_t i, j;
805
806         /*
807          * Flags should always be zero when the change notify
808          * is registered by the client's spooler.  A user Win32 app
809          * might use the flags though instead of the NOTIFY_OPTION_INFO
810          * --jerry
811          */
812
813         if (!option) {
814                 return false;
815         }
816
817         if (p->notify.flags)
818                 return is_monitoring_event_flags(
819                         p->notify.flags, notify_type, notify_field);
820
821         for (i = 0; i < option->count; i++) {
822
823                 /* Check match for notify_type */
824
825                 if (option->types[i].type != notify_type)
826                         continue;
827
828                 /* Check match for field */
829
830                 for (j = 0; j < option->types[i].count; j++) {
831                         if (option->types[i].fields[j].field == notify_field) {
832                                 return true;
833                         }
834                 }
835         }
836
837         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
838                    p->servername, p->sharename, notify_type, notify_field));
839
840         return false;
841 }
842
843 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
844         _data->data.integer[0] = _integer; \
845         _data->data.integer[1] = 0;
846
847
848 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
849         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
850         if (!_data->data.string.string) {\
851                 _data->data.string.size = 0; \
852         } \
853         _data->data.string.size = strlen_m_term(_p) * 2;
854
855 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
856         _data->data.devmode.devmode = _devmode;
857
858 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
859         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
860         if (!_data->data.sd.sd) { \
861                 _data->data.sd.sd_size = 0; \
862         } \
863         _data->data.sd.sd_size = \
864                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
865
866 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
867                                    struct tm *t,
868                                    const char **pp,
869                                    uint32_t *plen)
870 {
871         struct spoolss_Time st;
872         uint32_t len = 16;
873         char *p;
874
875         if (!init_systemtime(&st, t)) {
876                 return;
877         }
878
879         p = talloc_array(mem_ctx, char, len);
880         if (!p) {
881                 return;
882         }
883
884         /*
885          * Systemtime must be linearized as a set of UINT16's.
886          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
887          */
888
889         SSVAL(p, 0, st.year);
890         SSVAL(p, 2, st.month);
891         SSVAL(p, 4, st.day_of_week);
892         SSVAL(p, 6, st.day);
893         SSVAL(p, 8, st.hour);
894         SSVAL(p, 10, st.minute);
895         SSVAL(p, 12, st.second);
896         SSVAL(p, 14, st.millisecond);
897
898         *pp = p;
899         *plen = len;
900 }
901
902 /* Convert a notification message to a struct spoolss_Notify */
903
904 static void notify_one_value(struct spoolss_notify_msg *msg,
905                              struct spoolss_Notify *data,
906                              TALLOC_CTX *mem_ctx)
907 {
908         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
909 }
910
911 static void notify_string(struct spoolss_notify_msg *msg,
912                           struct spoolss_Notify *data,
913                           TALLOC_CTX *mem_ctx)
914 {
915         /* The length of the message includes the trailing \0 */
916
917         data->data.string.size = msg->len * 2;
918         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
919         if (!data->data.string.string) {
920                 data->data.string.size = 0;
921                 return;
922         }
923 }
924
925 static void notify_system_time(struct spoolss_notify_msg *msg,
926                                struct spoolss_Notify *data,
927                                TALLOC_CTX *mem_ctx)
928 {
929         data->data.string.string = NULL;
930         data->data.string.size = 0;
931
932         if (msg->len != sizeof(time_t)) {
933                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
934                           msg->len));
935                 return;
936         }
937
938         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
939                                &data->data.string.string,
940                                &data->data.string.size);
941 }
942
943 struct notify2_message_table {
944         const char *name;
945         void (*fn)(struct spoolss_notify_msg *msg,
946                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
947 };
948
949 static struct notify2_message_table printer_notify_table[] = {
950         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
951         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
952         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
953         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
954         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
955         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
956         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
957         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
958         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
959         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
960         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
961         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
962         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
963         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
964         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
965         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
966         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
967         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
968         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
969 };
970
971 static struct notify2_message_table job_notify_table[] = {
972         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
973         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
974         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
975         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
976         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
977         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
978         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
979         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
980         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
981         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
982         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
983         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
984         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
985         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
986         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
987         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
988         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
989         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
990         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
991         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
992         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
993         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
994         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
995         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
996 };
997
998
999 /***********************************************************************
1000  Allocate talloc context for container object
1001  **********************************************************************/
1002
1003 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1004 {
1005         if ( !ctr )
1006                 return;
1007
1008         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1009
1010         return;
1011 }
1012
1013 /***********************************************************************
1014  release all allocated memory and zero out structure
1015  **********************************************************************/
1016
1017 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1018 {
1019         if ( !ctr )
1020                 return;
1021
1022         if ( ctr->ctx )
1023                 talloc_destroy(ctr->ctx);
1024
1025         ZERO_STRUCTP(ctr);
1026
1027         return;
1028 }
1029
1030 /***********************************************************************
1031  **********************************************************************/
1032
1033 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1034 {
1035         if ( !ctr )
1036                 return NULL;
1037
1038         return ctr->ctx;
1039 }
1040
1041 /***********************************************************************
1042  **********************************************************************/
1043
1044 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1045 {
1046         if ( !ctr || !ctr->msg_groups )
1047                 return NULL;
1048
1049         if ( idx >= ctr->num_groups )
1050                 return NULL;
1051
1052         return &ctr->msg_groups[idx];
1053
1054 }
1055
1056 /***********************************************************************
1057  How many groups of change messages do we have ?
1058  **********************************************************************/
1059
1060 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1061 {
1062         if ( !ctr )
1063                 return 0;
1064
1065         return ctr->num_groups;
1066 }
1067
1068 /***********************************************************************
1069  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1070  **********************************************************************/
1071
1072 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1073 {
1074         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1075         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1076         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1077         int                             i, new_slot;
1078
1079         if ( !ctr || !msg )
1080                 return 0;
1081
1082         /* loop over all groups looking for a matching printer name */
1083
1084         for ( i=0; i<ctr->num_groups; i++ ) {
1085                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1086                         break;
1087         }
1088
1089         /* add a new group? */
1090
1091         if ( i == ctr->num_groups ) {
1092                 ctr->num_groups++;
1093
1094                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1095                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1096                         return 0;
1097                 }
1098                 ctr->msg_groups = groups;
1099
1100                 /* clear the new entry and set the printer name */
1101
1102                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1103                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1104         }
1105
1106         /* add the change messages; 'i' is the correct index now regardless */
1107
1108         msg_grp = &ctr->msg_groups[i];
1109
1110         msg_grp->num_msgs++;
1111
1112         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1113                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1114                 return 0;
1115         }
1116         msg_grp->msgs = msg_list;
1117
1118         new_slot = msg_grp->num_msgs-1;
1119         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1120
1121         /* need to allocate own copy of data */
1122
1123         if ( msg->len != 0 )
1124                 msg_grp->msgs[new_slot].notify.data = (char *)
1125                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1126
1127         return ctr->num_groups;
1128 }
1129
1130 static void construct_info_data(struct spoolss_Notify *info_data,
1131                                 enum spoolss_NotifyType type,
1132                                 uint16_t field, int id);
1133
1134 /***********************************************************************
1135  Send a change notication message on all handles which have a call
1136  back registered
1137  **********************************************************************/
1138
1139 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1140                                   struct printer_handle *prn_hnd,
1141                                   SPOOLSS_NOTIFY_MSG *messages,
1142                                   uint32_t num_msgs,
1143                                   struct spoolss_Notify **_notifies,
1144                                   int *_count)
1145 {
1146         struct spoolss_Notify *notifies;
1147         SPOOLSS_NOTIFY_MSG *msg;
1148         int count = 0;
1149         uint32_t id;
1150         int i;
1151
1152         notifies = talloc_zero_array(mem_ctx,
1153                                      struct spoolss_Notify, num_msgs);
1154         if (!notifies) {
1155                 return ENOMEM;
1156         }
1157
1158         for (i = 0; i < num_msgs; i++) {
1159
1160                 msg = &messages[i];
1161
1162                 /* Are we monitoring this event? */
1163
1164                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1165                         continue;
1166                 }
1167
1168                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1169                            "for printer [%s]\n",
1170                            msg->type, msg->field, prn_hnd->sharename));
1171
1172                 /*
1173                  * if the is a printer notification handle and not a job
1174                  * notification type, then set the id to 0.
1175                  * Otherwise just use what was specified in the message.
1176                  *
1177                  * When registering change notification on a print server
1178                  * handle we always need to send back the id (snum) matching
1179                  * the printer for which the change took place.
1180                  * For change notify registered on a printer handle,
1181                  * this does not matter and the id should be 0.
1182                  *
1183                  * --jerry
1184                  */
1185
1186                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1187                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1188                         id = 0;
1189                 } else {
1190                         id = msg->id;
1191                 }
1192
1193                 /* Convert unix jobid to smb jobid */
1194
1195                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1196                         id = sysjob_to_jobid(msg->id);
1197
1198                         if (id == -1) {
1199                                 DEBUG(3, ("no such unix jobid %d\n",
1200                                           msg->id));
1201                                 continue;
1202                         }
1203                 }
1204
1205                 construct_info_data(&notifies[count],
1206                                     msg->type, msg->field, id);
1207
1208                 switch(msg->type) {
1209                 case PRINTER_NOTIFY_TYPE:
1210                         if (printer_notify_table[msg->field].fn) {
1211                                 printer_notify_table[msg->field].fn(msg,
1212                                                 &notifies[count], mem_ctx);
1213                         }
1214                         break;
1215
1216                 case JOB_NOTIFY_TYPE:
1217                         if (job_notify_table[msg->field].fn) {
1218                                 job_notify_table[msg->field].fn(msg,
1219                                                 &notifies[count], mem_ctx);
1220                         }
1221                         break;
1222
1223                 default:
1224                         DEBUG(5, ("Unknown notification type %d\n",
1225                                   msg->type));
1226                         continue;
1227                 }
1228
1229                 count++;
1230         }
1231
1232         *_notifies = notifies;
1233         *_count = count;
1234
1235         return 0;
1236 }
1237
1238 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1239                                 struct printer_handle *prn_hnd,
1240                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1241 {
1242         struct spoolss_Notify *notifies;
1243         int count = 0;
1244         union spoolss_ReplyPrinterInfo info;
1245         struct spoolss_NotifyInfo info0;
1246         uint32_t reply_result;
1247         NTSTATUS status;
1248         WERROR werr;
1249         int ret;
1250
1251         /* Is there notification on this handle? */
1252         if (prn_hnd->notify.cli_chan == NULL ||
1253             prn_hnd->notify.cli_chan->active_connections == 0) {
1254                 return 0;
1255         }
1256
1257         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1258                    prn_hnd->servername, prn_hnd->sharename));
1259
1260         /* For this printer? Print servers always receive notifications. */
1261         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1262             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1263                 return 0;
1264         }
1265
1266         DEBUG(10,("Our printer\n"));
1267
1268         /* build the array of change notifications */
1269         ret = build_notify2_messages(mem_ctx, prn_hnd,
1270                                      msg_group->msgs,
1271                                      msg_group->num_msgs,
1272                                      &notifies, &count);
1273         if (ret) {
1274                 return ret;
1275         }
1276
1277         info0.version   = 0x2;
1278         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1279         info0.count     = count;
1280         info0.notifies  = notifies;
1281
1282         info.info0 = &info0;
1283
1284         status = dcerpc_spoolss_RouterReplyPrinterEx(
1285                                 prn_hnd->notify.cli_chan->binding_handle,
1286                                 mem_ctx,
1287                                 &prn_hnd->notify.cli_hnd,
1288                                 prn_hnd->notify.change, /* color */
1289                                 prn_hnd->notify.flags,
1290                                 &reply_result,
1291                                 0, /* reply_type, must be 0 */
1292                                 info, &werr);
1293         if (!NT_STATUS_IS_OK(status)) {
1294                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1295                           "failed: %s\n",
1296                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1297                           nt_errstr(status)));
1298                 werr = ntstatus_to_werror(status);
1299         } else if (!W_ERROR_IS_OK(werr)) {
1300                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1301                           "failed: %s\n",
1302                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1303                           win_errstr(werr)));
1304         }
1305         switch (reply_result) {
1306         case 0:
1307                 break;
1308         case PRINTER_NOTIFY_INFO_DISCARDED:
1309         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1310         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1311                 break;
1312         default:
1313                 break;
1314         }
1315
1316         return 0;
1317 }
1318
1319 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1320 {
1321         struct printer_handle    *p;
1322         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1323         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1324         int ret;
1325
1326         if ( !msg_group ) {
1327                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1328                 return;
1329         }
1330
1331         if (!msg_group->msgs) {
1332                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1333                 return;
1334         }
1335
1336         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1337
1338         /* loop over all printers */
1339
1340         for (p = printers_list; p; p = p->next) {
1341                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1342                 if (ret) {
1343                         goto done;
1344                 }
1345         }
1346
1347 done:
1348         DEBUG(8,("send_notify2_changes: Exit...\n"));
1349         return;
1350 }
1351
1352 /***********************************************************************
1353  **********************************************************************/
1354
1355 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1356 {
1357
1358         uint32_t tv_sec, tv_usec;
1359         size_t offset = 0;
1360
1361         /* Unpack message */
1362
1363         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1364                              msg->printer);
1365
1366         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1367                                 &tv_sec, &tv_usec,
1368                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1369
1370         if (msg->len == 0)
1371                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1372                            &msg->notify.value[0], &msg->notify.value[1]);
1373         else
1374                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1375                            &msg->len, &msg->notify.data);
1376
1377         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1378                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1379
1380         tv->tv_sec = tv_sec;
1381         tv->tv_usec = tv_usec;
1382
1383         if (msg->len == 0)
1384                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1385                           msg->notify.value[1]));
1386         else
1387                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1388
1389         return true;
1390 }
1391
1392 /********************************************************************
1393  Receive a notify2 message list
1394  ********************************************************************/
1395
1396 static void receive_notify2_message_list(struct messaging_context *msg,
1397                                          void *private_data,
1398                                          uint32_t msg_type,
1399                                          struct server_id server_id,
1400                                          DATA_BLOB *data)
1401 {
1402         size_t                  msg_count, i;
1403         char                    *buf = (char *)data->data;
1404         char                    *msg_ptr;
1405         size_t                  msg_len;
1406         SPOOLSS_NOTIFY_MSG      notify;
1407         SPOOLSS_NOTIFY_MSG_CTR  messages;
1408         int                     num_groups;
1409
1410         if (data->length < 4) {
1411                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1412                 return;
1413         }
1414
1415         msg_count = IVAL(buf, 0);
1416         msg_ptr = buf + 4;
1417
1418         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1419
1420         if (msg_count == 0) {
1421                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1422                 return;
1423         }
1424
1425         /* initialize the container */
1426
1427         ZERO_STRUCT( messages );
1428         notify_msg_ctr_init( &messages );
1429
1430         /*
1431          * build message groups for each printer identified
1432          * in a change_notify msg.  Remember that a PCN message
1433          * includes the handle returned for the srv_spoolss_replyopenprinter()
1434          * call.  Therefore messages are grouped according to printer handle.
1435          */
1436
1437         for ( i=0; i<msg_count; i++ ) {
1438                 struct timeval msg_tv;
1439
1440                 if (msg_ptr + 4 - buf > data->length) {
1441                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1442                         return;
1443                 }
1444
1445                 msg_len = IVAL(msg_ptr,0);
1446                 msg_ptr += 4;
1447
1448                 if (msg_ptr + msg_len - buf > data->length) {
1449                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1450                         return;
1451                 }
1452
1453                 /* unpack messages */
1454
1455                 ZERO_STRUCT( notify );
1456                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1457                 msg_ptr += msg_len;
1458
1459                 /* add to correct list in container */
1460
1461                 notify_msg_ctr_addmsg( &messages, &notify );
1462
1463                 /* free memory that might have been allocated by notify2_unpack_msg() */
1464
1465                 if ( notify.len != 0 )
1466                         SAFE_FREE( notify.notify.data );
1467         }
1468
1469         /* process each group of messages */
1470
1471         num_groups = notify_msg_ctr_numgroups( &messages );
1472         for ( i=0; i<num_groups; i++ )
1473                 send_notify2_changes( &messages, i );
1474
1475
1476         /* cleanup */
1477
1478         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1479                 (uint32_t)msg_count ));
1480
1481         notify_msg_ctr_destroy( &messages );
1482
1483         return;
1484 }
1485
1486 /********************************************************************
1487  Send a message to ourself about new driver being installed
1488  so we can upgrade the information for each printer bound to this
1489  driver
1490  ********************************************************************/
1491
1492 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1493                                             struct messaging_context *msg_ctx)
1494 {
1495         int len = strlen(drivername);
1496
1497         if (!len)
1498                 return false;
1499
1500         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1501                 drivername));
1502
1503         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1504                            MSG_PRINTER_DRVUPGRADE,
1505                            (const uint8_t *)drivername, len+1);
1506
1507         return true;
1508 }
1509
1510 void srv_spoolss_cleanup(void)
1511 {
1512         struct printer_session_counter *session_counter;
1513
1514         for (session_counter = counter_list;
1515              session_counter != NULL;
1516              session_counter = counter_list) {
1517                 DLIST_REMOVE(counter_list, session_counter);
1518                 TALLOC_FREE(session_counter);
1519         }
1520 }
1521
1522 /**********************************************************************
1523  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1524  over all printers, upgrading ones as necessary
1525  **********************************************************************/
1526
1527 void do_drv_upgrade_printer(struct messaging_context *msg,
1528                             void *private_data,
1529                             uint32_t msg_type,
1530                             struct server_id server_id,
1531                             DATA_BLOB *data)
1532 {
1533         TALLOC_CTX *tmp_ctx;
1534         struct auth_serversupplied_info *session_info = NULL;
1535         struct spoolss_PrinterInfo2 *pinfo2;
1536         NTSTATUS status;
1537         WERROR result;
1538         const char *drivername;
1539         int snum;
1540         int n_services = lp_numservices();
1541
1542         tmp_ctx = talloc_new(NULL);
1543         if (!tmp_ctx) return;
1544
1545         status = make_session_info_system(tmp_ctx, &session_info);
1546         if (!NT_STATUS_IS_OK(status)) {
1547                 DEBUG(0, ("do_drv_upgrade_printer: "
1548                           "Could not create system session_info\n"));
1549                 goto done;
1550         }
1551
1552         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1553         if (!drivername) {
1554                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1555                 goto done;
1556         }
1557
1558         DEBUG(10, ("do_drv_upgrade_printer: "
1559                    "Got message for new driver [%s]\n", drivername));
1560
1561         /* Iterate the printer list */
1562
1563         for (snum = 0; snum < n_services; snum++) {
1564                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1565                         continue;
1566                 }
1567
1568                 /* ignore [printers] share */
1569                 if (strequal(lp_const_servicename(snum), "printers")) {
1570                         continue;
1571                 }
1572
1573                 result = winreg_get_printer(tmp_ctx, session_info, msg,
1574                                             lp_const_servicename(snum),
1575                                             &pinfo2);
1576
1577                 if (!W_ERROR_IS_OK(result)) {
1578                         continue;
1579                 }
1580
1581                 if (!pinfo2->drivername) {
1582                         continue;
1583                 }
1584
1585                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1586                         continue;
1587                 }
1588
1589                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1590
1591                 /* all we care about currently is the change_id */
1592                 result = winreg_printer_update_changeid(tmp_ctx,
1593                                                         session_info,
1594                                                         msg,
1595                                                         pinfo2->printername);
1596
1597                 if (!W_ERROR_IS_OK(result)) {
1598                         DEBUG(3, ("do_drv_upgrade_printer: "
1599                                   "Failed to update changeid [%s]\n",
1600                                   win_errstr(result)));
1601                 }
1602         }
1603
1604         /* all done */
1605 done:
1606         talloc_free(tmp_ctx);
1607 }
1608
1609 /********************************************************************
1610  Update the cache for all printq's with a registered client
1611  connection
1612  ********************************************************************/
1613
1614 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1615 {
1616         struct printer_handle *printer = printers_list;
1617         int snum;
1618
1619         /* loop through all printers and update the cache where
1620            a client is connected */
1621         while (printer) {
1622                 if ((printer->printer_type == SPLHND_PRINTER) &&
1623                     ((printer->notify.cli_chan != NULL) &&
1624                      (printer->notify.cli_chan->active_connections > 0))) {
1625                         snum = print_queue_snum(printer->sharename);
1626                         print_queue_status(msg_ctx, snum, NULL, NULL);
1627                 }
1628
1629                 printer = printer->next;
1630         }
1631
1632         return;
1633 }
1634
1635 /****************************************************************
1636  _spoolss_OpenPrinter
1637 ****************************************************************/
1638
1639 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1640                             struct spoolss_OpenPrinter *r)
1641 {
1642         struct spoolss_OpenPrinterEx e;
1643         WERROR werr;
1644
1645         ZERO_STRUCT(e.in.userlevel);
1646
1647         e.in.printername        = r->in.printername;
1648         e.in.datatype           = r->in.datatype;
1649         e.in.devmode_ctr        = r->in.devmode_ctr;
1650         e.in.access_mask        = r->in.access_mask;
1651         e.in.level              = 0;
1652
1653         e.out.handle            = r->out.handle;
1654
1655         werr = _spoolss_OpenPrinterEx(p, &e);
1656
1657         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1658                 /* OpenPrinterEx returns this for a bad
1659                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1660                  * instead.
1661                  */
1662                 werr = WERR_INVALID_PRINTER_NAME;
1663         }
1664
1665         return werr;
1666 }
1667
1668 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1669                               struct spoolss_DeviceMode *orig,
1670                               struct spoolss_DeviceMode **dest)
1671 {
1672         struct spoolss_DeviceMode *dm;
1673
1674         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1675         if (!dm) {
1676                 return WERR_NOMEM;
1677         }
1678
1679         /* copy all values, then duplicate strings and structs */
1680         *dm = *orig;
1681
1682         dm->devicename = talloc_strdup(dm, orig->devicename);
1683         if (!dm->devicename) {
1684                 return WERR_NOMEM;
1685         }
1686         dm->formname = talloc_strdup(dm, orig->formname);
1687         if (!dm->formname) {
1688                 return WERR_NOMEM;
1689         }
1690         if (orig->driverextra_data.data) {
1691                 dm->driverextra_data.data =
1692                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1693                                         orig->driverextra_data.length);
1694                 if (!dm->driverextra_data.data) {
1695                         return WERR_NOMEM;
1696                 }
1697         }
1698
1699         *dest = dm;
1700         return WERR_OK;
1701 }
1702
1703 /****************************************************************
1704  _spoolss_OpenPrinterEx
1705 ****************************************************************/
1706
1707 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1708                               struct spoolss_OpenPrinterEx *r)
1709 {
1710         int snum;
1711         struct printer_handle *Printer=NULL;
1712         WERROR result;
1713
1714         if (!r->in.printername) {
1715                 return WERR_INVALID_PARAM;
1716         }
1717
1718         if (r->in.level > 3) {
1719                 return WERR_INVALID_PARAM;
1720         }
1721         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1722             (r->in.level == 2 && !r->in.userlevel.level2) ||
1723             (r->in.level == 3 && !r->in.userlevel.level3)) {
1724                 return WERR_INVALID_PARAM;
1725         }
1726
1727         /* some sanity check because you can open a printer or a print server */
1728         /* aka: \\server\printer or \\server */
1729
1730         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1731
1732         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1733         if (!W_ERROR_IS_OK(result)) {
1734                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1735                         "for printer %s\n", r->in.printername));
1736                 ZERO_STRUCTP(r->out.handle);
1737                 return result;
1738         }
1739
1740         Printer = find_printer_index_by_hnd(p, r->out.handle);
1741         if ( !Printer ) {
1742                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1743                         "handle we created for printer %s\n", r->in.printername));
1744                 close_printer_handle(p, r->out.handle);
1745                 ZERO_STRUCTP(r->out.handle);
1746                 return WERR_INVALID_PARAM;
1747         }
1748
1749         /*
1750          * First case: the user is opening the print server:
1751          *
1752          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1753          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1754          *
1755          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1756          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1757          * or if the user is listed in the smb.conf printer admin parameter.
1758          *
1759          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1760          * client view printer folder, but does not show the MSAPW.
1761          *
1762          * Note: this test needs code to check access rights here too. Jeremy
1763          * could you look at this?
1764          *
1765          * Second case: the user is opening a printer:
1766          * NT doesn't let us connect to a printer if the connecting user
1767          * doesn't have print permission.
1768          *
1769          * Third case: user is opening a Port Monitor
1770          * access checks same as opening a handle to the print server.
1771          */
1772
1773         switch (Printer->printer_type )
1774         {
1775         case SPLHND_SERVER:
1776         case SPLHND_PORTMON_TCP:
1777         case SPLHND_PORTMON_LOCAL:
1778                 /* Printserver handles use global struct... */
1779
1780                 snum = -1;
1781
1782                 /* Map standard access rights to object specific access rights */
1783
1784                 se_map_standard(&r->in.access_mask,
1785                                 &printserver_std_mapping);
1786
1787                 /* Deny any object specific bits that don't apply to print
1788                    servers (i.e printer and job specific bits) */
1789
1790                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1791
1792                 if (r->in.access_mask &
1793                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1794                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1795                         close_printer_handle(p, r->out.handle);
1796                         ZERO_STRUCTP(r->out.handle);
1797                         return WERR_ACCESS_DENIED;
1798                 }
1799
1800                 /* Allow admin access */
1801
1802                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1803                 {
1804                         if (!lp_ms_add_printer_wizard()) {
1805                                 close_printer_handle(p, r->out.handle);
1806                                 ZERO_STRUCTP(r->out.handle);
1807                                 return WERR_ACCESS_DENIED;
1808                         }
1809
1810                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1811                            and not a printer admin, then fail */
1812
1813                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1814                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1815                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1816                             !token_contains_name_in_list(
1817                                     uidtoname(p->session_info->utok.uid),
1818                                     p->session_info->info3->base.domain.string,
1819                                     NULL,
1820                                     p->session_info->security_token,
1821                                     lp_printer_admin(snum))) {
1822                                 close_printer_handle(p, r->out.handle);
1823                                 ZERO_STRUCTP(r->out.handle);
1824                                 DEBUG(3,("access DENIED as user is not root, "
1825                                         "has no printoperator privilege, "
1826                                         "not a member of the printoperator builtin group and "
1827                                         "is not in printer admin list"));
1828                                 return WERR_ACCESS_DENIED;
1829                         }
1830
1831                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1832                 }
1833                 else
1834                 {
1835                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1836                 }
1837
1838                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1839                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1840
1841                 /* We fall through to return WERR_OK */
1842                 break;
1843
1844         case SPLHND_PRINTER:
1845                 /* NT doesn't let us connect to a printer if the connecting user
1846                    doesn't have print permission.  */
1847
1848                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1849                         close_printer_handle(p, r->out.handle);
1850                         ZERO_STRUCTP(r->out.handle);
1851                         return WERR_BADFID;
1852                 }
1853
1854                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1855                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1856                 }
1857
1858                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1859
1860                 /* map an empty access mask to the minimum access mask */
1861                 if (r->in.access_mask == 0x0)
1862                         r->in.access_mask = PRINTER_ACCESS_USE;
1863
1864                 /*
1865                  * If we are not serving the printer driver for this printer,
1866                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1867                  * will keep NT clients happy  --jerry
1868                  */
1869
1870                 if (lp_use_client_driver(snum)
1871                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1872                 {
1873                         r->in.access_mask = PRINTER_ACCESS_USE;
1874                 }
1875
1876                 /* check smb.conf parameters and the the sec_desc */
1877
1878                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1879                                   p->client_id->name, p->client_id->addr)) {
1880                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1881                         ZERO_STRUCTP(r->out.handle);
1882                         return WERR_ACCESS_DENIED;
1883                 }
1884
1885                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1886                                    p->session_info->security_token, snum) ||
1887                     !print_access_check(p->session_info,
1888                                         p->msg_ctx,
1889                                         snum,
1890                                         r->in.access_mask)) {
1891                         DEBUG(3, ("access DENIED for printer open\n"));
1892                         close_printer_handle(p, r->out.handle);
1893                         ZERO_STRUCTP(r->out.handle);
1894                         return WERR_ACCESS_DENIED;
1895                 }
1896
1897                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1898                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1899                         close_printer_handle(p, r->out.handle);
1900                         ZERO_STRUCTP(r->out.handle);
1901                         return WERR_ACCESS_DENIED;
1902                 }
1903
1904                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1905                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1906                 else
1907                         r->in.access_mask = PRINTER_ACCESS_USE;
1908
1909                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1910                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1911
1912                 winreg_create_printer(p->mem_ctx,
1913                                       get_session_info_system(),
1914                                       p->msg_ctx,
1915                                       lp_const_servicename(snum));
1916
1917                 break;
1918
1919         default:
1920                 /* sanity check to prevent programmer error */
1921                 ZERO_STRUCTP(r->out.handle);
1922                 return WERR_BADFID;
1923         }
1924
1925         Printer->access_granted = r->in.access_mask;
1926
1927         /*
1928          * If the client sent a devmode in the OpenPrinter() call, then
1929          * save it here in case we get a job submission on this handle
1930          */
1931
1932          if ((Printer->printer_type != SPLHND_SERVER) &&
1933              r->in.devmode_ctr.devmode) {
1934                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1935                                 &Printer->devmode);
1936          }
1937
1938 #if 0   /* JERRY -- I'm doubtful this is really effective */
1939         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1940            optimization in Windows 2000 clients  --jerry */
1941
1942         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1943                 && (RA_WIN2K == get_remote_arch()) )
1944         {
1945                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1946                 sys_usleep( 500000 );
1947         }
1948 #endif
1949
1950         return WERR_OK;
1951 }
1952
1953 /****************************************************************
1954  _spoolss_ClosePrinter
1955 ****************************************************************/
1956
1957 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1958                              struct spoolss_ClosePrinter *r)
1959 {
1960         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1961
1962         if (Printer && Printer->document_started) {
1963                 struct spoolss_EndDocPrinter e;
1964
1965                 e.in.handle = r->in.handle;
1966
1967                 _spoolss_EndDocPrinter(p, &e);
1968         }
1969
1970         if (!close_printer_handle(p, r->in.handle))
1971                 return WERR_BADFID;
1972
1973         /* clear the returned printer handle.  Observed behavior
1974            from Win2k server.  Don't think this really matters.
1975            Previous code just copied the value of the closed
1976            handle.    --jerry */
1977
1978         ZERO_STRUCTP(r->out.handle);
1979
1980         return WERR_OK;
1981 }
1982
1983 /****************************************************************
1984  _spoolss_DeletePrinter
1985 ****************************************************************/
1986
1987 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1988                               struct spoolss_DeletePrinter *r)
1989 {
1990         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1991         WERROR result;
1992         int snum;
1993
1994         if (Printer && Printer->document_started) {
1995                 struct spoolss_EndDocPrinter e;
1996
1997                 e.in.handle = r->in.handle;
1998
1999                 _spoolss_EndDocPrinter(p, &e);
2000         }
2001
2002         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2003                 winreg_delete_printer_key(p->mem_ctx,
2004                                           get_session_info_system(),
2005                                           p->msg_ctx,
2006                                           lp_const_servicename(snum),
2007                                           "");
2008         }
2009
2010         result = delete_printer_handle(p, r->in.handle);
2011
2012         return result;
2013 }
2014
2015 /*******************************************************************
2016  * static function to lookup the version id corresponding to an
2017  * long architecture string
2018  ******************************************************************/
2019
2020 static const struct print_architecture_table_node archi_table[]= {
2021
2022         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2023         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2024         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2025         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2026         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2027         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2028         {"Windows x64",          SPL_ARCH_X64,          3 },
2029         {NULL,                   "",            -1 }
2030 };
2031
2032 static int get_version_id(const char *arch)
2033 {
2034         int i;
2035
2036         for (i=0; archi_table[i].long_archi != NULL; i++)
2037         {
2038                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2039                         return (archi_table[i].version);
2040         }
2041
2042         return -1;
2043 }
2044
2045 /****************************************************************
2046  _spoolss_DeletePrinterDriver
2047 ****************************************************************/
2048
2049 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2050                                     struct spoolss_DeletePrinterDriver *r)
2051 {
2052
2053         struct spoolss_DriverInfo8 *info = NULL;
2054         struct spoolss_DriverInfo8 *info_win2k = NULL;
2055         int                             version;
2056         WERROR                          status;
2057
2058         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2059            and not a printer admin, then fail */
2060
2061         if ( (p->session_info->utok.uid != sec_initial_uid())
2062              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2063                 && !token_contains_name_in_list(
2064                         uidtoname(p->session_info->utok.uid),
2065                         p->session_info->info3->base.domain.string,
2066                         NULL,
2067                         p->session_info->security_token,
2068                         lp_printer_admin(-1)) )
2069         {
2070                 return WERR_ACCESS_DENIED;
2071         }
2072
2073         /* check that we have a valid driver name first */
2074
2075         if ((version = get_version_id(r->in.architecture)) == -1)
2076                 return WERR_INVALID_ENVIRONMENT;
2077
2078         status = winreg_get_driver(p->mem_ctx,
2079                                    get_session_info_system(),
2080                                    p->msg_ctx,
2081                                    r->in.architecture, r->in.driver,
2082                                    version, &info);
2083         if (!W_ERROR_IS_OK(status)) {
2084                 /* try for Win2k driver if "Windows NT x86" */
2085
2086                 if ( version == 2 ) {
2087                         version = 3;
2088
2089                         status = winreg_get_driver(p->mem_ctx,
2090                                                    get_session_info_system(),
2091                                                    p->msg_ctx,
2092                                                    r->in.architecture,
2093                                                    r->in.driver,
2094                                                    version, &info);
2095                         if (!W_ERROR_IS_OK(status)) {
2096                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2097                                 goto done;
2098                         }
2099                 }
2100                 /* otherwise it was a failure */
2101                 else {
2102                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2103                         goto done;
2104                 }
2105
2106         }
2107
2108         if (printer_driver_in_use(p->mem_ctx,
2109                                   get_session_info_system(),
2110                                   p->msg_ctx,
2111                                   info)) {
2112                 status = WERR_PRINTER_DRIVER_IN_USE;
2113                 goto done;
2114         }
2115
2116         if (version == 2) {
2117                 status = winreg_get_driver(p->mem_ctx,
2118                                            get_session_info_system(),
2119                                            p->msg_ctx,
2120                                            r->in.architecture,
2121                                            r->in.driver, 3, &info_win2k);
2122                 if (W_ERROR_IS_OK(status)) {
2123                         /* if we get to here, we now have 2 driver info structures to remove */
2124                         /* remove the Win2k driver first*/
2125
2126                         status = winreg_del_driver(p->mem_ctx,
2127                                                    get_session_info_system(),
2128                                                    p->msg_ctx,
2129                                                    info_win2k, 3);
2130                         talloc_free(info_win2k);
2131
2132                         /* this should not have failed---if it did, report to client */
2133                         if (!W_ERROR_IS_OK(status)) {
2134                                 goto done;
2135                         }
2136                 }
2137         }
2138
2139         status = winreg_del_driver(p->mem_ctx,
2140                                    get_session_info_system(),
2141                                    p->msg_ctx,
2142                                    info, version);
2143
2144 done:
2145         talloc_free(info);
2146
2147         return status;
2148 }
2149
2150 /****************************************************************
2151  _spoolss_DeletePrinterDriverEx
2152 ****************************************************************/
2153
2154 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2155                                       struct spoolss_DeletePrinterDriverEx *r)
2156 {
2157         struct spoolss_DriverInfo8      *info = NULL;
2158         struct spoolss_DriverInfo8      *info_win2k = NULL;
2159         int                             version;
2160         bool                            delete_files;
2161         WERROR                          status;
2162
2163         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2164            and not a printer admin, then fail */
2165
2166         if ( (p->session_info->utok.uid != sec_initial_uid())
2167                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2168                 && !token_contains_name_in_list(
2169                         uidtoname(p->session_info->utok.uid),
2170                         p->session_info->info3->base.domain.string,
2171                         NULL,
2172                         p->session_info->security_token, lp_printer_admin(-1)) )
2173         {
2174                 return WERR_ACCESS_DENIED;
2175         }
2176
2177         /* check that we have a valid driver name first */
2178         if ((version = get_version_id(r->in.architecture)) == -1) {
2179                 /* this is what NT returns */
2180                 return WERR_INVALID_ENVIRONMENT;
2181         }
2182
2183         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2184                 version = r->in.version;
2185
2186         status = winreg_get_driver(p->mem_ctx,
2187                                    get_session_info_system(),
2188                                    p->msg_ctx,
2189                                    r->in.architecture,
2190                                    r->in.driver,
2191                                    version,
2192                                    &info);
2193         if (!W_ERROR_IS_OK(status)) {
2194                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2195
2196                 /*
2197                  * if the client asked for a specific version,
2198                  * or this is something other than Windows NT x86,
2199                  * then we've failed
2200                  */
2201
2202                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2203                         goto done;
2204
2205                 /* try for Win2k driver if "Windows NT x86" */
2206
2207                 version = 3;
2208                 status = winreg_get_driver(info,
2209                                            get_session_info_system(),
2210                                            p->msg_ctx,
2211                                            r->in.architecture,
2212                                            r->in.driver,
2213                                            version, &info);
2214                 if (!W_ERROR_IS_OK(status)) {
2215                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2216                         goto done;
2217                 }
2218         }
2219
2220         if (printer_driver_in_use(info,
2221                                   get_session_info_system(),
2222                                   p->msg_ctx,
2223                                   info)) {
2224                 status = WERR_PRINTER_DRIVER_IN_USE;
2225                 goto done;
2226         }
2227
2228         /*
2229          * we have a couple of cases to consider.
2230          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2231          *     then the delete should fail if **any** files overlap with
2232          *     other drivers
2233          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2234          *     non-overlapping files
2235          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2236          *     is set, the do not delete any files
2237          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2238          */
2239
2240         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2241
2242         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2243
2244         if (delete_files &&
2245             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2246             printer_driver_files_in_use(info,
2247                                         get_session_info_system(),
2248                                         p->msg_ctx,
2249                                         info)) {
2250                 /* no idea of the correct error here */
2251                 status = WERR_ACCESS_DENIED;
2252                 goto done;
2253         }
2254
2255
2256         /* also check for W32X86/3 if necessary; maybe we already have? */
2257
2258         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2259                 status = winreg_get_driver(info,
2260                                            get_session_info_system(),
2261                                            p->msg_ctx,
2262                                            r->in.architecture,
2263                                            r->in.driver, 3, &info_win2k);
2264                 if (W_ERROR_IS_OK(status)) {
2265
2266                         if (delete_files &&
2267                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2268                             printer_driver_files_in_use(info,
2269                                                         get_session_info_system(),
2270                                                         p->msg_ctx,
2271                                                         info_win2k)) {
2272                                 /* no idea of the correct error here */
2273                                 talloc_free(info_win2k);
2274                                 status = WERR_ACCESS_DENIED;
2275                                 goto done;
2276                         }
2277
2278                         /* if we get to here, we now have 2 driver info structures to remove */
2279                         /* remove the Win2k driver first*/
2280
2281                         status = winreg_del_driver(info,
2282                                                    get_session_info_system(),
2283                                                    p->msg_ctx,
2284                                                    info_win2k,
2285                                                    3);
2286
2287                         /* this should not have failed---if it did, report to client */
2288
2289                         if (!W_ERROR_IS_OK(status)) {
2290                                 goto done;
2291                         }
2292
2293                         /*
2294                          * now delete any associated files if delete_files is
2295                          * true. Even if this part failes, we return succes
2296                          * because the driver doesn not exist any more
2297                          */
2298                         if (delete_files) {
2299                                 delete_driver_files(get_session_info_system(),
2300                                                     info_win2k);
2301                         }
2302                 }
2303         }
2304
2305         status = winreg_del_driver(info,
2306                                    get_session_info_system(),
2307                                    p->msg_ctx,
2308                                    info,
2309                                    version);
2310         if (!W_ERROR_IS_OK(status)) {
2311                 goto done;
2312         }
2313
2314         /*
2315          * now delete any associated files if delete_files is
2316          * true. Even if this part failes, we return succes
2317          * because the driver doesn not exist any more
2318          */
2319         if (delete_files) {
2320                 delete_driver_files(get_session_info_system(), info);
2321         }
2322
2323 done:
2324         talloc_free(info);
2325         return status;
2326 }
2327
2328
2329 /********************************************************************
2330  GetPrinterData on a printer server Handle.
2331 ********************************************************************/
2332
2333 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2334                                             const char *value,
2335                                             enum winreg_Type *type,
2336                                             union spoolss_PrinterData *data)
2337 {
2338         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2339
2340         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2341                 *type = REG_DWORD;
2342                 data->value = 0x00;
2343                 return WERR_OK;
2344         }
2345
2346         if (!StrCaseCmp(value, "BeepEnabled")) {
2347                 *type = REG_DWORD;
2348                 data->value = 0x00;
2349                 return WERR_OK;
2350         }
2351
2352         if (!StrCaseCmp(value, "EventLog")) {
2353                 *type = REG_DWORD;
2354                 /* formally was 0x1b */
2355                 data->value = 0x00;
2356                 return WERR_OK;
2357         }
2358
2359         if (!StrCaseCmp(value, "NetPopup")) {
2360                 *type = REG_DWORD;
2361                 data->value = 0x00;
2362                 return WERR_OK;
2363         }
2364
2365         if (!StrCaseCmp(value, "MajorVersion")) {
2366                 *type = REG_DWORD;
2367
2368                 /* Windows NT 4.0 seems to not allow uploading of drivers
2369                    to a server that reports 0x3 as the MajorVersion.
2370                    need to investigate more how Win2k gets around this .
2371                    -- jerry */
2372
2373                 if (RA_WINNT == get_remote_arch()) {
2374                         data->value = 0x02;
2375                 } else {
2376                         data->value = 0x03;
2377                 }
2378
2379                 return WERR_OK;
2380         }
2381
2382         if (!StrCaseCmp(value, "MinorVersion")) {
2383                 *type = REG_DWORD;
2384                 data->value = 0x00;
2385                 return WERR_OK;
2386         }
2387
2388         /* REG_BINARY
2389          *  uint32_t size        = 0x114
2390          *  uint32_t major       = 5
2391          *  uint32_t minor       = [0|1]
2392          *  uint32_t build       = [2195|2600]
2393          *  extra unicode string = e.g. "Service Pack 3"
2394          */
2395         if (!StrCaseCmp(value, "OSVersion")) {
2396                 DATA_BLOB blob;
2397                 enum ndr_err_code ndr_err;
2398                 struct spoolss_OSVersion os;
2399
2400                 os.major                = 5;    /* Windows 2000 == 5.0 */
2401                 os.minor                = 0;
2402                 os.build                = 2195; /* build */
2403                 os.extra_string         = "";   /* leave extra string empty */
2404
2405                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2406                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2407                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2408                         return WERR_GENERAL_FAILURE;
2409                 }
2410
2411                 *type = REG_BINARY;
2412                 data->binary = blob;
2413
2414                 return WERR_OK;
2415         }
2416
2417
2418         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2419                 *type = REG_SZ;
2420
2421                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2422                 W_ERROR_HAVE_NO_MEMORY(data->string);
2423
2424                 return WERR_OK;
2425         }
2426
2427         if (!StrCaseCmp(value, "Architecture")) {
2428                 *type = REG_SZ;
2429                 data->string = talloc_strdup(mem_ctx,
2430                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2431                 W_ERROR_HAVE_NO_MEMORY(data->string);
2432
2433                 return WERR_OK;
2434         }
2435
2436         if (!StrCaseCmp(value, "DsPresent")) {
2437                 *type = REG_DWORD;
2438
2439                 /* only show the publish check box if we are a
2440                    member of a AD domain */
2441
2442                 if (lp_security() == SEC_ADS) {
2443                         data->value = 0x01;
2444                 } else {
2445                         data->value = 0x00;
2446                 }
2447                 return WERR_OK;
2448         }
2449
2450         if (!StrCaseCmp(value, "DNSMachineName")) {
2451                 const char *hostname = get_mydnsfullname();
2452
2453                 if (!hostname) {
2454                         return WERR_BADFILE;
2455                 }
2456
2457                 *type = REG_SZ;
2458                 data->string = talloc_strdup(mem_ctx, hostname);
2459                 W_ERROR_HAVE_NO_MEMORY(data->string);
2460
2461                 return WERR_OK;
2462         }
2463
2464         *type = REG_NONE;
2465
2466         return WERR_INVALID_PARAM;
2467 }
2468
2469 /****************************************************************
2470  _spoolss_GetPrinterData
2471 ****************************************************************/
2472
2473 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2474                                struct spoolss_GetPrinterData *r)
2475 {
2476         struct spoolss_GetPrinterDataEx r2;
2477
2478         r2.in.handle            = r->in.handle;
2479         r2.in.key_name          = "PrinterDriverData";
2480         r2.in.value_name        = r->in.value_name;
2481         r2.in.offered           = r->in.offered;
2482         r2.out.type             = r->out.type;
2483         r2.out.data             = r->out.data;
2484         r2.out.needed           = r->out.needed;
2485
2486         return _spoolss_GetPrinterDataEx(p, &r2);
2487 }
2488
2489 /*********************************************************
2490  Connect to the client machine.
2491 **********************************************************/
2492
2493 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2494                         struct sockaddr_storage *client_ss, const char *remote_machine)
2495 {
2496         NTSTATUS ret;
2497         struct cli_state *the_cli;
2498         struct sockaddr_storage rm_addr;
2499         char addr[INET6_ADDRSTRLEN];
2500
2501         if ( is_zero_addr(client_ss) ) {
2502                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2503                         remote_machine));
2504                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2505                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2506                         return false;
2507                 }
2508                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2509         } else {
2510                 rm_addr = *client_ss;
2511                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2512                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2513                         addr));
2514         }
2515
2516         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2517                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2518                         addr));
2519                 return false;
2520         }
2521
2522         /* setup the connection */
2523         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2524                 &rm_addr, 0, "IPC$", "IPC",
2525                 "", /* username */
2526                 "", /* domain */
2527                 "", /* password */
2528                 0, lp_client_signing());
2529
2530         if ( !NT_STATUS_IS_OK( ret ) ) {
2531                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2532                         remote_machine ));
2533                 return false;
2534         }
2535
2536         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2537                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2538                 cli_shutdown(the_cli);
2539                 return false;
2540         }
2541
2542         /*
2543          * Ok - we have an anonymous connection to the IPC$ share.
2544          * Now start the NT Domain stuff :-).
2545          */
2546
2547         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2548         if (!NT_STATUS_IS_OK(ret)) {
2549                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2550                         remote_machine, nt_errstr(ret)));
2551                 cli_shutdown(the_cli);
2552                 return false;
2553         }
2554
2555         return true;
2556 }
2557
2558 /***************************************************************************
2559  Connect to the client.
2560 ****************************************************************************/
2561
2562 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2563                                         uint32_t localprinter,
2564                                         enum winreg_Type type,
2565                                         struct policy_handle *handle,
2566                                         struct notify_back_channel **_chan,
2567                                         struct sockaddr_storage *client_ss,
2568                                         struct messaging_context *msg_ctx)
2569 {
2570         WERROR result;
2571         NTSTATUS status;
2572         struct notify_back_channel *chan;
2573
2574         for (chan = back_channels; chan; chan = chan->next) {
2575                 if (memcmp(&chan->client_address, client_ss,
2576                            sizeof(struct sockaddr_storage)) == 0) {
2577                         break;
2578                 }
2579         }
2580
2581         /*
2582          * If it's the first connection, contact the client
2583          * and connect to the IPC$ share anonymously
2584          */
2585         if (!chan) {
2586                 fstring unix_printer;
2587
2588                 /* the +2 is to strip the leading 2 backslashs */
2589                 fstrcpy(unix_printer, printer + 2);
2590
2591                 chan = talloc_zero(back_channels, struct notify_back_channel);
2592                 if (!chan) {
2593                         return false;
2594                 }
2595                 chan->client_address = *client_ss;
2596
2597                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2598                         TALLOC_FREE(chan);
2599                         return false;
2600                 }
2601                 chan->binding_handle = chan->cli_pipe->binding_handle;
2602
2603                 DLIST_ADD(back_channels, chan);
2604
2605                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2606                                    receive_notify2_message_list);
2607                 /* Tell the connections db we're now interested in printer
2608                  * notify messages. */
2609                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2610                                             true, FLAG_MSG_PRINT_NOTIFY);
2611         }
2612
2613         /*
2614          * Tell the specific printing tdb we want messages for this printer
2615          * by registering our PID.
2616          */
2617
2618         if (!print_notify_register_pid(snum)) {
2619                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2620                           printer));
2621         }
2622
2623         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2624                                                  talloc_tos(),
2625                                                  printer,
2626                                                  localprinter,
2627                                                  type,
2628                                                  0,
2629                                                  NULL,
2630                                                  handle,
2631                                                  &result);
2632         if (!NT_STATUS_IS_OK(status)) {
2633                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2634                 result = ntstatus_to_werror(status);
2635         } else if (!W_ERROR_IS_OK(result)) {
2636                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2637         }
2638
2639         chan->active_connections++;
2640         *_chan = chan;
2641
2642         return (W_ERROR_IS_OK(result));
2643 }
2644
2645 /****************************************************************
2646  ****************************************************************/
2647
2648 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2649                                                              const struct spoolss_NotifyOption *r)
2650 {
2651         struct spoolss_NotifyOption *option;
2652         uint32_t i,k;
2653
2654         if (!r) {
2655                 return NULL;
2656         }
2657
2658         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2659         if (!option) {
2660                 return NULL;
2661         }
2662
2663         *option = *r;
2664
2665         if (!option->count) {
2666                 return option;
2667         }
2668
2669         option->types = talloc_zero_array(option,
2670                 struct spoolss_NotifyOptionType, option->count);
2671         if (!option->types) {
2672                 talloc_free(option);
2673                 return NULL;
2674         }
2675
2676         for (i=0; i < option->count; i++) {
2677                 option->types[i] = r->types[i];
2678
2679                 if (option->types[i].count) {
2680                         option->types[i].fields = talloc_zero_array(option,
2681                                 union spoolss_Field, option->types[i].count);
2682                         if (!option->types[i].fields) {
2683                                 talloc_free(option);
2684                                 return NULL;
2685                         }
2686                         for (k=0; k<option->types[i].count; k++) {
2687                                 option->types[i].fields[k] =
2688                                         r->types[i].fields[k];
2689                         }
2690                 }
2691         }
2692
2693         return option;
2694 }
2695
2696 /****************************************************************
2697  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2698  *
2699  * before replying OK: status=0 a rpc call is made to the workstation
2700  * asking ReplyOpenPrinter
2701  *
2702  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2703  * called from api_spoolss_rffpcnex
2704 ****************************************************************/
2705
2706 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2707                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2708 {
2709         int snum = -1;
2710         struct spoolss_NotifyOption *option = r->in.notify_options;
2711         struct sockaddr_storage client_ss;
2712
2713         /* store the notify value in the printer struct */
2714
2715         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2716
2717         if (!Printer) {
2718                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2719                         "Invalid handle (%s:%u:%u).\n",
2720                         OUR_HANDLE(r->in.handle)));
2721                 return WERR_BADFID;
2722         }
2723
2724         Printer->notify.flags           = r->in.flags;
2725         Printer->notify.options         = r->in.options;
2726         Printer->notify.printerlocal    = r->in.printer_local;
2727         Printer->notify.msg_ctx         = p->msg_ctx;
2728
2729         TALLOC_FREE(Printer->notify.option);
2730         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2731
2732         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2733
2734         /* Connect to the client machine and send a ReplyOpenPrinter */
2735
2736         if ( Printer->printer_type == SPLHND_SERVER)
2737                 snum = -1;
2738         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2739                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2740                 return WERR_BADFID;
2741
2742         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2743                 "client_address is %s\n", p->client_id->addr));
2744
2745         if (!lp_print_notify_backchannel(snum)) {
2746                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2747                         "backchannel disabled\n"));
2748                 return WERR_SERVER_UNAVAILABLE;
2749         }
2750
2751         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2752                                    AI_NUMERICHOST)) {
2753                 return WERR_SERVER_UNAVAILABLE;
2754         }
2755
2756         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2757                                         Printer->notify.printerlocal, REG_SZ,
2758                                         &Printer->notify.cli_hnd,
2759                                         &Printer->notify.cli_chan,
2760                                         &client_ss, p->msg_ctx)) {
2761                 return WERR_SERVER_UNAVAILABLE;
2762         }
2763
2764         return WERR_OK;
2765 }
2766
2767 /*******************************************************************
2768  * fill a notify_info_data with the servername
2769  ********************************************************************/
2770
2771 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2772                                        int snum,
2773                                        struct spoolss_Notify *data,
2774                                        print_queue_struct *queue,
2775                                        struct spoolss_PrinterInfo2 *pinfo2,
2776                                        TALLOC_CTX *mem_ctx)
2777 {
2778         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2779 }
2780
2781 /*******************************************************************
2782  * fill a notify_info_data with the printername (not including the servername).
2783  ********************************************************************/
2784
2785 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2786                                         int snum,
2787                                         struct spoolss_Notify *data,
2788                                         print_queue_struct *queue,
2789                                         struct spoolss_PrinterInfo2 *pinfo2,
2790                                         TALLOC_CTX *mem_ctx)
2791 {
2792         /* the notify name should not contain the \\server\ part */
2793         const char *p = strrchr(pinfo2->printername, '\\');
2794
2795         if (!p) {
2796                 p = pinfo2->printername;
2797         } else {
2798                 p++;
2799         }
2800
2801         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2802 }
2803
2804 /*******************************************************************
2805  * fill a notify_info_data with the servicename
2806  ********************************************************************/
2807
2808 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2809                                       int snum,
2810                                       struct spoolss_Notify *data,
2811                                       print_queue_struct *queue,
2812                                       struct spoolss_PrinterInfo2 *pinfo2,
2813                                       TALLOC_CTX *mem_ctx)
2814 {
2815         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2816 }
2817
2818 /*******************************************************************
2819  * fill a notify_info_data with the port name
2820  ********************************************************************/
2821
2822 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2823                                      int snum,
2824                                      struct spoolss_Notify *data,
2825                                      print_queue_struct *queue,
2826                                      struct spoolss_PrinterInfo2 *pinfo2,
2827                                      TALLOC_CTX *mem_ctx)
2828 {
2829         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2830 }
2831
2832 /*******************************************************************
2833  * fill a notify_info_data with the printername
2834  * but it doesn't exist, have to see what to do
2835  ********************************************************************/
2836
2837 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2838                                        int snum,
2839                                        struct spoolss_Notify *data,
2840                                        print_queue_struct *queue,
2841                                        struct spoolss_PrinterInfo2 *pinfo2,
2842                                        TALLOC_CTX *mem_ctx)
2843 {
2844         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2845 }
2846
2847 /*******************************************************************
2848  * fill a notify_info_data with the comment
2849  ********************************************************************/
2850
2851 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2852                                    int snum,
2853                                    struct spoolss_Notify *data,
2854                                    print_queue_struct *queue,
2855                                    struct spoolss_PrinterInfo2 *pinfo2,
2856                                    TALLOC_CTX *mem_ctx)
2857 {
2858         const char *p;
2859
2860         if (*pinfo2->comment == '\0') {
2861                 p = lp_comment(snum);
2862         } else {
2863                 p = pinfo2->comment;
2864         }
2865
2866         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2867 }
2868
2869 /*******************************************************************
2870  * fill a notify_info_data with the comment
2871  * location = "Room 1, floor 2, building 3"
2872  ********************************************************************/
2873
2874 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2875                                     int snum,
2876                                     struct spoolss_Notify *data,
2877                                     print_queue_struct *queue,
2878                                     struct spoolss_PrinterInfo2 *pinfo2,
2879                                     TALLOC_CTX *mem_ctx)
2880 {
2881         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2882 }
2883
2884 /*******************************************************************
2885  * fill a notify_info_data with the device mode
2886  * jfm:xxxx don't to it for know but that's a real problem !!!
2887  ********************************************************************/
2888
2889 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2890                                    int snum,
2891                                    struct spoolss_Notify *data,
2892                                    print_queue_struct *queue,
2893                                    struct spoolss_PrinterInfo2 *pinfo2,
2894                                    TALLOC_CTX *mem_ctx)
2895 {
2896         /* for a dummy implementation we have to zero the fields */
2897         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2898 }
2899
2900 /*******************************************************************
2901  * fill a notify_info_data with the separator file name
2902  ********************************************************************/
2903
2904 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2905                                    int snum,
2906                                    struct spoolss_Notify *data,
2907                                    print_queue_struct *queue,
2908                                    struct spoolss_PrinterInfo2 *pinfo2,
2909                                    TALLOC_CTX *mem_ctx)
2910 {
2911         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2912 }
2913
2914 /*******************************************************************
2915  * fill a notify_info_data with the print processor
2916  * jfm:xxxx return always winprint to indicate we don't do anything to it
2917  ********************************************************************/
2918
2919 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2920                                            int snum,
2921                                            struct spoolss_Notify *data,
2922                                            print_queue_struct *queue,
2923                                            struct spoolss_PrinterInfo2 *pinfo2,
2924                                            TALLOC_CTX *mem_ctx)
2925 {
2926         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2927 }
2928
2929 /*******************************************************************
2930  * fill a notify_info_data with the print processor options
2931  * jfm:xxxx send an empty string
2932  ********************************************************************/
2933
2934 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2935                                       int snum,
2936                                       struct spoolss_Notify *data,
2937                                       print_queue_struct *queue,
2938                                       struct spoolss_PrinterInfo2 *pinfo2,
2939                                       TALLOC_CTX *mem_ctx)
2940 {
2941         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2942 }
2943
2944 /*******************************************************************
2945  * fill a notify_info_data with the data type
2946  * jfm:xxxx always send RAW as data type
2947  ********************************************************************/
2948
2949 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2950                                     int snum,
2951                                     struct spoolss_Notify *data,
2952                                     print_queue_struct *queue,
2953                                     struct spoolss_PrinterInfo2 *pinfo2,
2954                                     TALLOC_CTX *mem_ctx)
2955 {
2956         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2957 }
2958
2959 /*******************************************************************
2960  * fill a notify_info_data with the security descriptor
2961  * jfm:xxxx send an null pointer to say no security desc
2962  * have to implement security before !
2963  ********************************************************************/
2964
2965 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2966                                          int snum,
2967                                          struct spoolss_Notify *data,
2968                                          print_queue_struct *queue,
2969                                          struct spoolss_PrinterInfo2 *pinfo2,
2970                                          TALLOC_CTX *mem_ctx)
2971 {
2972         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2973 }
2974
2975 /*******************************************************************
2976  * fill a notify_info_data with the attributes
2977  * jfm:xxxx a samba printer is always shared
2978  ********************************************************************/
2979
2980 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2981                                       int snum,
2982                                       struct spoolss_Notify *data,
2983                                       print_queue_struct *queue,
2984                                       struct spoolss_PrinterInfo2 *pinfo2,
2985                                       TALLOC_CTX *mem_ctx)
2986 {
2987         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2988 }
2989
2990 /*******************************************************************
2991  * fill a notify_info_data with the priority
2992  ********************************************************************/
2993
2994 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2995                                     int snum,
2996                                     struct spoolss_Notify *data,
2997                                     print_queue_struct *queue,
2998                                     struct spoolss_PrinterInfo2 *pinfo2,
2999                                     TALLOC_CTX *mem_ctx)
3000 {
3001         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3002 }
3003
3004 /*******************************************************************
3005  * fill a notify_info_data with the default priority
3006  ********************************************************************/
3007
3008 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3009                                             int snum,
3010                                             struct spoolss_Notify *data,
3011                                             print_queue_struct *queue,
3012                                             struct spoolss_PrinterInfo2 *pinfo2,
3013                                             TALLOC_CTX *mem_ctx)
3014 {
3015         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3016 }
3017
3018 /*******************************************************************
3019  * fill a notify_info_data with the start time
3020  ********************************************************************/
3021
3022 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3023                                       int snum,
3024                                       struct spoolss_Notify *data,
3025                                       print_queue_struct *queue,
3026                                       struct spoolss_PrinterInfo2 *pinfo2,
3027                                       TALLOC_CTX *mem_ctx)
3028 {
3029         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3030 }
3031
3032 /*******************************************************************
3033  * fill a notify_info_data with the until time
3034  ********************************************************************/
3035
3036 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3037                                       int snum,
3038                                       struct spoolss_Notify *data,
3039                                       print_queue_struct *queue,
3040                                       struct spoolss_PrinterInfo2 *pinfo2,
3041                                       TALLOC_CTX *mem_ctx)
3042 {
3043         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3044 }
3045
3046 /*******************************************************************
3047  * fill a notify_info_data with the status
3048  ********************************************************************/
3049
3050 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3051                                   int snum,
3052                                   struct spoolss_Notify *data,
3053                                   print_queue_struct *queue,
3054                                   struct spoolss_PrinterInfo2 *pinfo2,
3055                                   TALLOC_CTX *mem_ctx)
3056 {
3057         print_status_struct status;
3058
3059         print_queue_length(msg_ctx, snum, &status);
3060         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3061 }
3062
3063 /*******************************************************************
3064  * fill a notify_info_data with the number of jobs queued
3065  ********************************************************************/
3066
3067 static void spoolss_notify_cjobs(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         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3075                 data, print_queue_length(msg_ctx, snum, NULL));
3076 }
3077
3078 /*******************************************************************
3079  * fill a notify_info_data with the average ppm
3080  ********************************************************************/
3081
3082 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3083                                        int snum,
3084                                        struct spoolss_Notify *data,
3085                                        print_queue_struct *queue,
3086                                        struct spoolss_PrinterInfo2 *pinfo2,
3087                                        TALLOC_CTX *mem_ctx)
3088 {
3089         /* always respond 8 pages per minutes */
3090         /* a little hard ! */
3091         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3092 }
3093
3094 /*******************************************************************
3095  * fill a notify_info_data with username
3096  ********************************************************************/
3097
3098 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3099                                     int snum,
3100                                     struct spoolss_Notify *data,
3101                                     print_queue_struct *queue,
3102                                     struct spoolss_PrinterInfo2 *pinfo2,
3103                                     TALLOC_CTX *mem_ctx)
3104 {
3105         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3106 }
3107
3108 /*******************************************************************
3109  * fill a notify_info_data with job status
3110  ********************************************************************/
3111
3112 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3113                                       int snum,
3114                                       struct spoolss_Notify *data,
3115                                       print_queue_struct *queue,
3116                                       struct spoolss_PrinterInfo2 *pinfo2,
3117                                       TALLOC_CTX *mem_ctx)
3118 {
3119         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3120 }
3121
3122 /*******************************************************************
3123  * fill a notify_info_data with job name
3124  ********************************************************************/
3125
3126 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3127                                     int snum,
3128                                     struct spoolss_Notify *data,
3129                                     print_queue_struct *queue,
3130                                     struct spoolss_PrinterInfo2 *pinfo2,
3131                                     TALLOC_CTX *mem_ctx)
3132 {
3133         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3134 }
3135
3136 /*******************************************************************
3137  * fill a notify_info_data with job status
3138  ********************************************************************/
3139
3140 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3141                                              int snum,
3142                                              struct spoolss_Notify *data,
3143                                              print_queue_struct *queue,
3144                                              struct spoolss_PrinterInfo2 *pinfo2,
3145                                              TALLOC_CTX *mem_ctx)
3146 {
3147         /*
3148          * Now we're returning job status codes we just return a "" here. JRA.
3149          */
3150
3151         const char *p = "";
3152
3153 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3154         p = "unknown";
3155
3156         switch (queue->status) {
3157         case LPQ_QUEUED:
3158                 p = "Queued";
3159                 break;
3160         case LPQ_PAUSED:
3161                 p = "";    /* NT provides the paused string */
3162                 break;
3163         case LPQ_SPOOLING:
3164                 p = "Spooling";
3165                 break;
3166         case LPQ_PRINTING:
3167                 p = "Printing";
3168                 break;
3169         }
3170 #endif /* NO LONGER NEEDED. */
3171
3172         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3173 }
3174
3175 /*******************************************************************
3176  * fill a notify_info_data with job time
3177  ********************************************************************/
3178
3179 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3180                                     int snum,
3181                                     struct spoolss_Notify *data,
3182                                     print_queue_struct *queue,
3183                                     struct spoolss_PrinterInfo2 *pinfo2,
3184                                     TALLOC_CTX *mem_ctx)
3185 {
3186         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3187 }
3188
3189 /*******************************************************************
3190  * fill a notify_info_data with job size
3191  ********************************************************************/
3192
3193 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3194                                     int snum,
3195                                     struct spoolss_Notify *data,
3196                                     print_queue_struct *queue,
3197                                     struct spoolss_PrinterInfo2 *pinfo2,
3198                                     TALLOC_CTX *mem_ctx)
3199 {
3200         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3201 }
3202
3203 /*******************************************************************
3204  * fill a notify_info_data with page info
3205  ********************************************************************/
3206 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3207                                        int snum,
3208                                 struct spoolss_Notify *data,
3209                                 print_queue_struct *queue,
3210                                 struct spoolss_PrinterInfo2 *pinfo2,
3211                                 TALLOC_CTX *mem_ctx)
3212 {
3213         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3214 }
3215
3216 /*******************************************************************
3217  * fill a notify_info_data with pages printed info.
3218  ********************************************************************/
3219 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3220                                          int snum,
3221                                 struct spoolss_Notify *data,
3222                                 print_queue_struct *queue,
3223                                 struct spoolss_PrinterInfo2 *pinfo2,
3224                                 TALLOC_CTX *mem_ctx)
3225 {
3226         /* Add code when back-end tracks this */
3227         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3228 }
3229
3230 /*******************************************************************
3231  Fill a notify_info_data with job position.
3232  ********************************************************************/
3233
3234 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3235                                         int snum,
3236                                         struct spoolss_Notify *data,
3237                                         print_queue_struct *queue,
3238                                         struct spoolss_PrinterInfo2 *pinfo2,
3239                                         TALLOC_CTX *mem_ctx)
3240 {
3241         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3242 }
3243
3244 /*******************************************************************
3245  Fill a notify_info_data with submitted time.
3246  ********************************************************************/
3247
3248 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3249                                           int snum,
3250                                           struct spoolss_Notify *data,
3251                                           print_queue_struct *queue,
3252                                           struct spoolss_PrinterInfo2 *pinfo2,
3253                                           TALLOC_CTX *mem_ctx)
3254 {
3255         data->data.string.string = NULL;
3256         data->data.string.size = 0;
3257
3258         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3259                                &data->data.string.string,
3260                                &data->data.string.size);
3261
3262 }
3263
3264 struct s_notify_info_data_table
3265 {
3266         enum spoolss_NotifyType type;
3267         uint16_t field;
3268         const char *name;
3269         enum spoolss_NotifyTable variable_type;
3270         void (*fn) (struct messaging_context *msg_ctx,
3271                     int snum, struct spoolss_Notify *data,
3272                     print_queue_struct *queue,
3273                     struct spoolss_PrinterInfo2 *pinfo2,
3274                     TALLOC_CTX *mem_ctx);
3275 };
3276
3277 /* A table describing the various print notification constants and
3278    whether the notification data is a pointer to a variable sized
3279    buffer, a one value uint32_t or a two value uint32_t. */
3280
3281 static const struct s_notify_info_data_table notify_info_data_table[] =
3282 {
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3316 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3317 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3318 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3319 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3320 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3321 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3322 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3323 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3324 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3325 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3326 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3327 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3328 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3329 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3330 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3331 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3332 };
3333
3334 /*******************************************************************
3335  Return the variable_type of info_data structure.
3336 ********************************************************************/
3337
3338 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3339                                                                   uint16_t field)
3340 {
3341         int i=0;
3342
3343         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3344                 if ( (notify_info_data_table[i].type == type) &&
3345                      (notify_info_data_table[i].field == field) ) {
3346                         return notify_info_data_table[i].variable_type;
3347                 }
3348         }
3349
3350         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3351
3352         return (enum spoolss_NotifyTable) 0;
3353 }
3354
3355 /****************************************************************************
3356 ****************************************************************************/
3357
3358 static bool search_notify(enum spoolss_NotifyType type,
3359                           uint16_t field,
3360                           int *value)
3361 {
3362         int i;
3363
3364         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3365                 if (notify_info_data_table[i].type == type &&
3366                     notify_info_data_table[i].field == field &&
3367                     notify_info_data_table[i].fn != NULL) {
3368                         *value = i;
3369                         return true;
3370                 }
3371         }
3372
3373         return false;
3374 }
3375
3376 /****************************************************************************
3377 ****************************************************************************/
3378
3379 static void construct_info_data(struct spoolss_Notify *info_data,
3380                                 enum spoolss_NotifyType type,
3381                                 uint16_t field, int id)
3382 {
3383         info_data->type                 = type;
3384         info_data->field.field          = field;
3385         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3386         info_data->job_id               = id;
3387 }
3388
3389 /*******************************************************************
3390  *
3391  * fill a notify_info struct with info asked
3392  *
3393  ********************************************************************/
3394
3395 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3396                                           struct printer_handle *print_hnd,
3397                                           struct spoolss_NotifyInfo *info,
3398                                           struct spoolss_PrinterInfo2 *pinfo2,
3399                                           int snum,
3400                                           const struct spoolss_NotifyOptionType *option_type,
3401                                           uint32_t id,
3402                                           TALLOC_CTX *mem_ctx)
3403 {
3404         int field_num,j;
3405         enum spoolss_NotifyType type;
3406         uint16_t field;
3407
3408         struct spoolss_Notify *current_data;
3409         print_queue_struct *queue=NULL;
3410
3411         type = option_type->type;
3412
3413         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3414                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3415                 option_type->count, lp_servicename(snum)));
3416
3417         for(field_num=0; field_num < option_type->count; field_num++) {
3418                 field = option_type->fields[field_num].field;
3419
3420                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3421
3422                 if (!search_notify(type, field, &j) )
3423                         continue;
3424
3425                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3426                                                       struct spoolss_Notify,
3427                                                       info->count + 1);
3428                 if (info->notifies == NULL) {
3429                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3430                         return false;
3431                 }
3432
3433                 current_data = &info->notifies[info->count];
3434
3435                 construct_info_data(current_data, type, field, id);
3436
3437                 DEBUG(10, ("construct_notify_printer_info: "
3438                            "calling [%s]  snum=%d  printername=[%s])\n",
3439                            notify_info_data_table[j].name, snum,
3440                            pinfo2->printername));
3441
3442                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3443                                              queue, pinfo2, mem_ctx);
3444
3445                 info->count++;
3446         }
3447
3448         return true;
3449 }
3450
3451 /*******************************************************************
3452  *
3453  * fill a notify_info struct with info asked
3454  *
3455  ********************************************************************/
3456
3457 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3458                                        print_queue_struct *queue,
3459                                        struct spoolss_NotifyInfo *info,
3460                                        struct spoolss_PrinterInfo2 *pinfo2,
3461                                        int snum,
3462                                        const struct spoolss_NotifyOptionType *option_type,
3463                                        uint32_t id,
3464                                        TALLOC_CTX *mem_ctx)
3465 {
3466         int field_num,j;
3467         enum spoolss_NotifyType type;
3468         uint16_t field;
3469         struct spoolss_Notify *current_data;
3470
3471         DEBUG(4,("construct_notify_jobs_info\n"));
3472
3473         type = option_type->type;
3474
3475         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3476                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3477                 option_type->count));
3478
3479         for(field_num=0; field_num<option_type->count; field_num++) {
3480                 field = option_type->fields[field_num].field;
3481
3482                 if (!search_notify(type, field, &j) )
3483                         continue;
3484
3485                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3486                                                       struct spoolss_Notify,
3487                                                       info->count + 1);
3488                 if (info->notifies == NULL) {
3489                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3490                         return false;
3491                 }
3492
3493                 current_data=&(info->notifies[info->count]);
3494
3495                 construct_info_data(current_data, type, field, id);
3496                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3497                                              queue, pinfo2, mem_ctx);
3498                 info->count++;
3499         }
3500
3501         return true;
3502 }
3503
3504 /*
3505  * JFM: The enumeration is not that simple, it's even non obvious.
3506  *
3507  * let's take an example: I want to monitor the PRINTER SERVER for
3508  * the printer's name and the number of jobs currently queued.
3509  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3510  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3511  *
3512  * I have 3 printers on the back of my server.
3513  *
3514  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3515  * structures.
3516  *   Number     Data                    Id
3517  *      1       printer 1 name          1
3518  *      2       printer 1 cjob          1
3519  *      3       printer 2 name          2
3520  *      4       printer 2 cjob          2
3521  *      5       printer 3 name          3
3522  *      6       printer 3 name          3
3523  *
3524  * that's the print server case, the printer case is even worse.
3525  */
3526
3527 /*******************************************************************
3528  *
3529  * enumerate all printers on the printserver
3530  * fill a notify_info struct with info asked
3531  *
3532  ********************************************************************/
3533
3534 static WERROR printserver_notify_info(struct pipes_struct *p,
3535                                       struct policy_handle *hnd,
3536                                       struct spoolss_NotifyInfo *info,
3537                                       TALLOC_CTX *mem_ctx)
3538 {
3539         int snum;
3540         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3541         int n_services=lp_numservices();
3542         int i;
3543         struct spoolss_NotifyOption *option;
3544         struct spoolss_NotifyOptionType option_type;
3545         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3546         WERROR result;
3547
3548         DEBUG(4,("printserver_notify_info\n"));
3549
3550         if (!Printer)
3551                 return WERR_BADFID;
3552
3553         option = Printer->notify.option;
3554
3555         info->version   = 2;
3556         info->notifies  = NULL;
3557         info->count     = 0;
3558
3559         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3560            sending a ffpcn() request first */
3561
3562         if ( !option )
3563                 return WERR_BADFID;
3564
3565         for (i=0; i<option->count; i++) {
3566                 option_type = option->types[i];
3567
3568                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3569                         continue;
3570
3571                 for (snum = 0; snum < n_services; snum++) {
3572                         if (!lp_browseable(snum) ||
3573                             !lp_snum_ok(snum) ||
3574                             !lp_print_ok(snum)) {
3575                                 continue; /* skip */
3576                         }
3577
3578                         /* Maybe we should use the SYSTEM session_info here... */
3579                         result = winreg_get_printer(mem_ctx,
3580                                                     get_session_info_system(),
3581                                                     p->msg_ctx,
3582                                                     lp_servicename(snum),
3583                                                     &pinfo2);
3584                         if (!W_ERROR_IS_OK(result)) {
3585                                 DEBUG(4, ("printserver_notify_info: "
3586                                           "Failed to get printer [%s]\n",
3587                                           lp_servicename(snum)));
3588                                 continue;
3589                         }
3590
3591
3592                         construct_notify_printer_info(p->msg_ctx,
3593                                                       Printer, info,
3594                                                       pinfo2, snum,
3595                                                       &option_type, snum,
3596                                                       mem_ctx);
3597
3598                         TALLOC_FREE(pinfo2);
3599                 }
3600         }
3601
3602 #if 0
3603         /*
3604          * Debugging information, don't delete.
3605          */
3606
3607         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3608         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3609         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3610
3611         for (i=0; i<info->count; i++) {
3612                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3613                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3614                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3615         }
3616 #endif
3617
3618         return WERR_OK;
3619 }
3620
3621 /*******************************************************************
3622  *
3623  * fill a notify_info struct with info asked
3624  *
3625  ********************************************************************/
3626
3627 static WERROR printer_notify_info(struct pipes_struct *p,
3628                                   struct policy_handle *hnd,
3629                                   struct spoolss_NotifyInfo *info,
3630                                   TALLOC_CTX *mem_ctx)
3631 {
3632         int snum;
3633         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3634         int i;
3635         uint32_t id;
3636         struct spoolss_NotifyOption *option;
3637         struct spoolss_NotifyOptionType option_type;
3638         int count,j;
3639         print_queue_struct *queue=NULL;
3640         print_status_struct status;
3641         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3642         WERROR result;
3643
3644         DEBUG(4,("printer_notify_info\n"));
3645
3646         if (!Printer)
3647                 return WERR_BADFID;
3648
3649         option = Printer->notify.option;
3650         id = 0x0;
3651
3652         info->version   = 2;
3653         info->notifies  = NULL;
3654         info->count     = 0;
3655
3656         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3657            sending a ffpcn() request first */
3658
3659         if ( !option )
3660                 return WERR_BADFID;
3661
3662         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3663                 return WERR_BADFID;
3664         }
3665
3666         /* Maybe we should use the SYSTEM session_info here... */
3667         result = winreg_get_printer(mem_ctx,
3668                                     get_session_info_system(),
3669                                     p->msg_ctx,
3670                                     lp_servicename(snum), &pinfo2);
3671         if (!W_ERROR_IS_OK(result)) {
3672                 return WERR_BADFID;
3673         }
3674
3675         for (i=0; i<option->count; i++) {
3676                 option_type = option->types[i];
3677
3678                 switch (option_type.type) {
3679                 case PRINTER_NOTIFY_TYPE:
3680                         if (construct_notify_printer_info(p->msg_ctx,
3681                                                           Printer, info,
3682                                                           pinfo2, snum,
3683                                                           &option_type, id,
3684                                                           mem_ctx)) {
3685                                 id--;
3686                         }
3687                         break;
3688
3689                 case JOB_NOTIFY_TYPE:
3690
3691                         count = print_queue_status(p->msg_ctx, snum, &queue,
3692                                                    &status);
3693
3694                         for (j=0; j<count; j++) {
3695                                 construct_notify_jobs_info(p->msg_ctx,
3696                                                            &queue[j], info,
3697                                                            pinfo2, snum,
3698                                                            &option_type,
3699                                                            queue[j].job,
3700                                                            mem_ctx);
3701                         }
3702
3703                         SAFE_FREE(queue);
3704                         break;
3705                 }
3706         }
3707
3708         /*
3709          * Debugging information, don't delete.
3710          */
3711         /*
3712         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3713         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3714         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3715
3716         for (i=0; i<info->count; i++) {
3717                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3718                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3719                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3720         }
3721         */
3722
3723         talloc_free(pinfo2);
3724         return WERR_OK;
3725 }
3726
3727 /****************************************************************
3728  _spoolss_RouterRefreshPrinterChangeNotify
3729 ****************************************************************/
3730
3731 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3732                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3733 {
3734         struct spoolss_NotifyInfo *info;
3735
3736         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3737         WERROR result = WERR_BADFID;
3738
3739         /* we always have a spoolss_NotifyInfo struct */
3740         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3741         if (!info) {
3742                 result = WERR_NOMEM;
3743                 goto done;
3744         }
3745
3746         *r->out.info = info;
3747
3748         if (!Printer) {
3749                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3750                         "Invalid handle (%s:%u:%u).\n",
3751                         OUR_HANDLE(r->in.handle)));
3752                 goto done;
3753         }
3754
3755         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3756
3757         /*
3758          *      We are now using the change value, and
3759          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3760          *      I don't have a global notification system, I'm sending back all the
3761          *      information even when _NOTHING_ has changed.
3762          */
3763
3764         /* We need to keep track of the change value to send back in
3765            RRPCN replies otherwise our updates are ignored. */
3766
3767         Printer->notify.fnpcn = true;
3768
3769         if (Printer->notify.cli_chan != NULL &&
3770             Printer->notify.cli_chan->active_connections > 0) {
3771                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3772                         "Saving change value in request [%x]\n",
3773                         r->in.change_low));
3774                 Printer->notify.change = r->in.change_low;
3775         }
3776
3777         /* just ignore the spoolss_NotifyOption */
3778
3779         switch (Printer->printer_type) {
3780                 case SPLHND_SERVER:
3781                         result = printserver_notify_info(p, r->in.handle,
3782                                                          info, p->mem_ctx);
3783                         break;
3784
3785                 case SPLHND_PRINTER:
3786                         result = printer_notify_info(p, r->in.handle,
3787                                                      info, p->mem_ctx);
3788                         break;
3789         }
3790
3791         Printer->notify.fnpcn = false;
3792
3793 done:
3794         return result;
3795 }
3796
3797 /********************************************************************
3798  ********************************************************************/
3799
3800 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3801                                  const char *servername,
3802                                  const char *printername,
3803                                  const char **printername_p)
3804 {
3805         /* FIXME: add lp_force_printername() */
3806
3807         if (servername == NULL) {
3808                 *printername_p = talloc_strdup(mem_ctx, printername);
3809                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3810                 return WERR_OK;
3811         }
3812
3813         if (servername[0] == '\\' && servername[1] == '\\') {
3814                 servername += 2;
3815         }
3816
3817         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3818         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3819
3820         return WERR_OK;
3821 }
3822
3823 /********************************************************************
3824  ********************************************************************/
3825
3826 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3827                                           const char *printername)
3828 {
3829         if (dm == NULL) {
3830                 return;
3831         }
3832
3833         dm->devicename = talloc_strndup(dm, printername,
3834                                         MIN(strlen(printername), 31));
3835 }
3836
3837 /********************************************************************
3838  * construct_printer_info_0
3839  * fill a printer_info_0 struct
3840  ********************************************************************/
3841
3842 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3843                                       const struct auth_serversupplied_info *session_info,
3844                                       struct messaging_context *msg_ctx,
3845                                       struct spoolss_PrinterInfo2 *info2,
3846                                       const char *servername,
3847                                       struct spoolss_PrinterInfo0 *r,
3848                                       int snum)
3849 {
3850         int count;
3851         struct printer_session_counter *session_counter;
3852         struct timeval setuptime;
3853         print_status_struct status;
3854         WERROR result;
3855
3856         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3857         if (!W_ERROR_IS_OK(result)) {
3858                 return result;
3859         }
3860
3861         if (servername) {
3862                 r->servername = talloc_strdup(mem_ctx, servername);
3863                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3864         } else {
3865                 r->servername = NULL;
3866         }
3867
3868         count = print_queue_length(msg_ctx, snum, &status);
3869
3870         /* check if we already have a counter for this printer */
3871         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3872                 if (session_counter->snum == snum)
3873                         break;
3874         }
3875
3876         /* it's the first time, add it to the list */
3877         if (session_counter == NULL) {
3878                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3879                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3880                 session_counter->snum           = snum;
3881                 session_counter->counter        = 0;
3882                 DLIST_ADD(counter_list, session_counter);
3883         }
3884
3885         /* increment it */
3886         session_counter->counter++;
3887
3888         r->cjobs                        = count;
3889         r->total_jobs                   = 0;
3890         r->total_bytes                  = 0;
3891
3892         get_startup_time(&setuptime);
3893         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3894
3895         /* JFM:
3896          * the global_counter should be stored in a TDB as it's common to all the clients
3897          * and should be zeroed on samba startup
3898          */
3899         r->global_counter               = session_counter->counter;
3900         r->total_pages                  = 0;
3901         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3902         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3903         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3904         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3905         r->spooling                     = 0;
3906         r->max_spooling                 = 0;
3907         r->session_counter              = session_counter->counter;
3908         r->num_error_out_of_paper       = 0x0;
3909         r->num_error_not_ready          = 0x0;          /* number of print failure */
3910         r->job_error                    = 0x0;
3911         r->number_of_processors         = 0x1;
3912         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3913         r->high_part_total_bytes        = 0x0;
3914
3915         /* ChangeID in milliseconds*/
3916         winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3917                                     info2->sharename, &r->change_id);
3918
3919         r->last_error                   = WERR_OK;
3920         r->status                       = nt_printq_status(status.status);
3921         r->enumerate_network_printers   = 0x0;
3922         r->c_setprinter                 = 0x0;
3923         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3924         r->processor_level              = 0x6;          /* 6  ???*/
3925         r->ref_ic                       = 0;
3926         r->reserved2                    = 0;
3927         r->reserved3                    = 0;
3928
3929         return WERR_OK;
3930 }
3931
3932
3933 /********************************************************************
3934  * construct_printer_info1
3935  * fill a spoolss_PrinterInfo1 struct
3936 ********************************************************************/
3937
3938 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3939                                       const struct spoolss_PrinterInfo2 *info2,
3940                                       uint32_t flags,
3941                                       const char *servername,
3942                                       struct spoolss_PrinterInfo1 *r,
3943                                       int snum)
3944 {
3945         WERROR result;
3946
3947         r->flags                = flags;
3948
3949         if (info2->comment == NULL || info2->comment[0] == '\0') {
3950                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3951         } else {
3952                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3953         }
3954         W_ERROR_HAVE_NO_MEMORY(r->comment);
3955
3956         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3957         if (!W_ERROR_IS_OK(result)) {
3958                 return result;
3959         }
3960
3961         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3962                                                   r->name,
3963                                                   info2->drivername,
3964                                                   r->comment);
3965         W_ERROR_HAVE_NO_MEMORY(r->description);
3966
3967         return WERR_OK;
3968 }
3969
3970 /********************************************************************
3971  * construct_printer_info2
3972  * fill a spoolss_PrinterInfo2 struct
3973 ********************************************************************/
3974
3975 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3976                                       struct messaging_context *msg_ctx,
3977                                       const struct spoolss_PrinterInfo2 *info2,
3978                                       const char *servername,
3979                                       struct spoolss_PrinterInfo2 *r,
3980                                       int snum)
3981 {
3982         int count;
3983         print_status_struct status;
3984         WERROR result;
3985
3986         count = print_queue_length(msg_ctx, snum, &status);
3987
3988         if (servername) {
3989                 r->servername           = talloc_strdup(mem_ctx, servername);
3990                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3991         } else {
3992                 r->servername           = NULL;
3993         }
3994
3995         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3996         if (!W_ERROR_IS_OK(result)) {
3997                 return result;
3998         }
3999
4000         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4001         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4002         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4003         W_ERROR_HAVE_NO_MEMORY(r->portname);
4004         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4005         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4006
4007         if (info2->comment[0] == '\0') {
4008                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4009         } else {
4010                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4011         }
4012         W_ERROR_HAVE_NO_MEMORY(r->comment);
4013
4014         r->location             = talloc_strdup(mem_ctx, info2->location);
4015         W_ERROR_HAVE_NO_MEMORY(r->location);
4016         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4017         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4018         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4019         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4020         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4021         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4022         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4023         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4024
4025         r->attributes           = info2->attributes;
4026
4027         r->priority             = info2->priority;
4028         r->defaultpriority      = info2->defaultpriority;
4029         r->starttime            = info2->starttime;
4030         r->untiltime            = info2->untiltime;
4031         r->status               = nt_printq_status(status.status);
4032         r->cjobs                = count;
4033         r->averageppm           = info2->averageppm;
4034
4035         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4036         if (!r->devmode) {
4037                 DEBUG(8,("Returning NULL Devicemode!\n"));
4038         }
4039
4040         compose_devicemode_devicename(r->devmode, r->printername);
4041
4042         r->secdesc = NULL;
4043
4044         if (info2->secdesc != NULL) {
4045                 /* don't use talloc_steal() here unless you do a deep steal of all
4046                    the SEC_DESC members */
4047
4048                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4049         }
4050
4051         return WERR_OK;
4052 }
4053
4054 /********************************************************************
4055  * construct_printer_info3
4056  * fill a spoolss_PrinterInfo3 struct
4057  ********************************************************************/
4058
4059 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4060                                       const struct spoolss_PrinterInfo2 *info2,
4061                                       const char *servername,
4062                                       struct spoolss_PrinterInfo3 *r,
4063                                       int snum)
4064 {
4065         /* These are the components of the SD we are returning. */
4066
4067         if (info2->secdesc != NULL) {
4068                 /* don't use talloc_steal() here unless you do a deep steal of all
4069                    the SEC_DESC members */
4070
4071                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4072                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4073         }
4074
4075         return WERR_OK;
4076 }
4077
4078 /********************************************************************
4079  * construct_printer_info4
4080  * fill a spoolss_PrinterInfo4 struct
4081  ********************************************************************/
4082
4083 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4084                                       const struct spoolss_PrinterInfo2 *info2,
4085                                       const char *servername,
4086                                       struct spoolss_PrinterInfo4 *r,
4087                                       int snum)
4088 {
4089         WERROR result;
4090
4091         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4092         if (!W_ERROR_IS_OK(result)) {
4093                 return result;
4094         }
4095
4096         if (servername) {
4097                 r->servername   = talloc_strdup(mem_ctx, servername);
4098                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4099         } else {
4100                 r->servername = NULL;
4101         }
4102
4103         r->attributes   = info2->attributes;
4104
4105         return WERR_OK;
4106 }
4107
4108 /********************************************************************
4109  * construct_printer_info5
4110  * fill a spoolss_PrinterInfo5 struct
4111  ********************************************************************/
4112
4113 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4114                                       const struct spoolss_PrinterInfo2 *info2,
4115                                       const char *servername,
4116                                       struct spoolss_PrinterInfo5 *r,
4117                                       int snum)
4118 {
4119         WERROR result;
4120
4121         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4122         if (!W_ERROR_IS_OK(result)) {
4123                 return result;
4124         }
4125
4126         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4127         W_ERROR_HAVE_NO_MEMORY(r->portname);
4128
4129         r->attributes   = info2->attributes;
4130
4131         /* these two are not used by NT+ according to MSDN */
4132         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4133         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4134
4135         return WERR_OK;
4136 }
4137
4138 /********************************************************************
4139  * construct_printer_info_6
4140  * fill a spoolss_PrinterInfo6 struct
4141  ********************************************************************/
4142
4143 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4144                                       struct messaging_context *msg_ctx,
4145                                       const struct spoolss_PrinterInfo2 *info2,
4146                                       const char *servername,
4147                                       struct spoolss_PrinterInfo6 *r,
4148                                       int snum)
4149 {
4150         int count;
4151         print_status_struct status;
4152
4153         count = print_queue_length(msg_ctx, snum, &status);
4154
4155         r->status = nt_printq_status(status.status);
4156
4157         return WERR_OK;
4158 }
4159
4160 /********************************************************************
4161  * construct_printer_info7
4162  * fill a spoolss_PrinterInfo7 struct
4163  ********************************************************************/
4164
4165 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4166                                       struct messaging_context *msg_ctx,
4167                                       const char *servername,
4168                                       struct spoolss_PrinterInfo7 *r,
4169                                       int snum)
4170 {
4171         struct auth_serversupplied_info *session_info;
4172         struct GUID guid;
4173         NTSTATUS status;
4174
4175         status = make_session_info_system(mem_ctx, &session_info);
4176         if (!NT_STATUS_IS_OK(status)) {
4177                 DEBUG(0, ("construct_printer_info7: "
4178                           "Could not create system session_info\n"));
4179                 return WERR_NOMEM;
4180         }
4181
4182         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4183                                  servername,
4184                                  lp_servicename(snum), &guid, NULL)) {
4185                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4186                 r->action = DSPRINT_PUBLISH;
4187         } else {
4188                 r->guid = talloc_strdup(mem_ctx, "");
4189                 r->action = DSPRINT_UNPUBLISH;
4190         }
4191         W_ERROR_HAVE_NO_MEMORY(r->guid);
4192
4193         TALLOC_FREE(session_info);
4194         return WERR_OK;
4195 }
4196
4197 /********************************************************************
4198  * construct_printer_info8
4199  * fill a spoolss_PrinterInfo8 struct
4200  ********************************************************************/
4201
4202 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4203                                       const struct spoolss_PrinterInfo2 *info2,
4204                                       const char *servername,
4205                                       struct spoolss_DeviceModeInfo *r,
4206                                       int snum)
4207 {
4208         WERROR result;
4209         const char *printername;
4210
4211         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4212         if (!W_ERROR_IS_OK(result)) {
4213                 return result;
4214         }
4215
4216         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4217         if (!r->devmode) {
4218                 DEBUG(8,("Returning NULL Devicemode!\n"));
4219         }
4220
4221         compose_devicemode_devicename(r->devmode, printername);
4222
4223         return WERR_OK;
4224 }
4225
4226
4227 /********************************************************************
4228 ********************************************************************/
4229
4230 static bool snum_is_shared_printer(int snum)
4231 {
4232         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4233 }
4234
4235 /********************************************************************
4236  Spoolss_enumprinters.
4237 ********************************************************************/
4238
4239 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4240                                            const struct auth_serversupplied_info *session_info,
4241                                            struct messaging_context *msg_ctx,
4242                                            const char *servername,
4243                                            uint32_t level,
4244                                            uint32_t flags,
4245                                            union spoolss_PrinterInfo **info_p,
4246                                            uint32_t *count_p)
4247 {
4248         int snum;
4249         int n_services = lp_numservices();
4250         union spoolss_PrinterInfo *info = NULL;
4251         uint32_t count = 0;
4252         WERROR result = WERR_OK;
4253
4254         *count_p = 0;
4255         *info_p = NULL;
4256
4257         for (snum = 0; snum < n_services; snum++) {
4258
4259                 const char *printer;
4260                 struct spoolss_PrinterInfo2 *info2;
4261
4262                 if (!snum_is_shared_printer(snum)) {
4263                         continue;
4264                 }
4265
4266                 printer = lp_const_servicename(snum);
4267
4268                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4269                         printer, snum));
4270
4271                 result = winreg_create_printer(mem_ctx,
4272                                                session_info,
4273                                                msg_ctx,
4274                                                printer);
4275                 if (!W_ERROR_IS_OK(result)) {
4276                         goto out;
4277                 }
4278
4279                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4280                                             union spoolss_PrinterInfo,
4281                                             count + 1);
4282                 if (!info) {
4283                         result = WERR_NOMEM;
4284                         goto out;
4285                 }
4286
4287                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4288                                             printer, &info2);
4289                 if (!W_ERROR_IS_OK(result)) {
4290                         goto out;
4291                 }
4292
4293                 switch (level) {
4294                 case 0:
4295                         result = construct_printer_info0(info, session_info,
4296                                                          msg_ctx, info2,
4297                                                          servername,
4298                                                          &info[count].info0, snum);
4299                         break;
4300                 case 1:
4301                         result = construct_printer_info1(info, info2, flags,
4302                                                          servername,
4303                                                          &info[count].info1, snum);
4304                         break;
4305                 case 2:
4306                         result = construct_printer_info2(info, msg_ctx, info2,
4307                                                          servername,
4308                                                          &info[count].info2, snum);
4309                         break;
4310                 case 4:
4311                         result = construct_printer_info4(info, info2,
4312                                                          servername,
4313                                                          &info[count].info4, snum);
4314                         break;
4315                 case 5:
4316                         result = construct_printer_info5(info, info2,
4317                                                          servername,
4318                                                          &info[count].info5, snum);
4319                         break;
4320
4321                 default:
4322                         result = WERR_UNKNOWN_LEVEL;
4323                         goto out;
4324                 }
4325
4326                 if (!W_ERROR_IS_OK(result)) {
4327                         goto out;
4328                 }
4329
4330                 count++;
4331         }
4332
4333         *count_p = count;
4334         *info_p = info;
4335
4336  out:
4337         if (!W_ERROR_IS_OK(result)) {
4338                 TALLOC_FREE(info);
4339                 return result;
4340         }
4341
4342         *info_p = info;
4343
4344         return WERR_OK;
4345 }
4346
4347 /********************************************************************
4348  * handle enumeration of printers at level 0
4349  ********************************************************************/
4350
4351 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4352                                   const struct auth_serversupplied_info *session_info,
4353                                   struct messaging_context *msg_ctx,
4354                                   uint32_t flags,
4355                                   const char *servername,
4356                                   union spoolss_PrinterInfo **info,
4357                                   uint32_t *count)
4358 {
4359         DEBUG(4,("enum_all_printers_info_0\n"));
4360
4361         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4362                                             servername, 0, flags, info, count);
4363 }
4364
4365
4366 /********************************************************************
4367 ********************************************************************/
4368
4369 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4370                                        const struct auth_serversupplied_info *session_info,
4371                                        struct messaging_context *msg_ctx,
4372                                        const char *servername,
4373                                        uint32_t flags,
4374                                        union spoolss_PrinterInfo **info,
4375                                        uint32_t *count)
4376 {
4377         DEBUG(4,("enum_all_printers_info_1\n"));
4378
4379         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4380                                             servername, 1, flags, info, count);
4381 }
4382
4383 /********************************************************************
4384  enum_all_printers_info_1_local.
4385 *********************************************************************/
4386
4387 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4388                                              const struct auth_serversupplied_info *session_info,
4389                                              struct messaging_context *msg_ctx,
4390                                              const char *servername,
4391                                              union spoolss_PrinterInfo **info,
4392                                              uint32_t *count)
4393 {
4394         DEBUG(4,("enum_all_printers_info_1_local\n"));
4395
4396         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4397                                         servername, PRINTER_ENUM_ICON8, info, count);
4398 }
4399
4400 /********************************************************************
4401  enum_all_printers_info_1_name.
4402 *********************************************************************/
4403
4404 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4405                                             const struct auth_serversupplied_info *session_info,
4406                                             struct messaging_context *msg_ctx,
4407                                             const char *servername,
4408                                             union spoolss_PrinterInfo **info,
4409                                             uint32_t *count)
4410 {
4411         const char *s = servername;
4412
4413         DEBUG(4,("enum_all_printers_info_1_name\n"));
4414
4415         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4416                 s = servername + 2;
4417         }
4418
4419         if (!is_myname_or_ipaddr(s)) {
4420                 return WERR_INVALID_NAME;
4421         }
4422
4423         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4424                                         servername, PRINTER_ENUM_ICON8, info, count);
4425 }
4426
4427 /********************************************************************
4428  enum_all_printers_info_1_network.
4429 *********************************************************************/
4430
4431 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4432                                                const struct auth_serversupplied_info *session_info,
4433                                                struct messaging_context *msg_ctx,
4434                                                const char *servername,
4435                                                union spoolss_PrinterInfo **info,
4436                                                uint32_t *count)
4437 {
4438         const char *s = servername;
4439
4440         DEBUG(4,("enum_all_printers_info_1_network\n"));
4441
4442         /* If we respond to a enum_printers level 1 on our name with flags
4443            set to PRINTER_ENUM_REMOTE with a list of printers then these
4444            printers incorrectly appear in the APW browse list.
4445            Specifically the printers for the server appear at the workgroup
4446            level where all the other servers in the domain are
4447            listed. Windows responds to this call with a
4448            WERR_CAN_NOT_COMPLETE so we should do the same. */
4449
4450         if (servername[0] == '\\' && servername[1] == '\\') {
4451                  s = servername + 2;
4452         }
4453
4454         if (is_myname_or_ipaddr(s)) {
4455                  return WERR_CAN_NOT_COMPLETE;
4456         }
4457
4458         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4459                                         servername, PRINTER_ENUM_NAME, info, count);
4460 }
4461
4462 /********************************************************************
4463  * api_spoolss_enumprinters
4464  *
4465  * called from api_spoolss_enumprinters (see this to understand)
4466  ********************************************************************/
4467
4468 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4469                                        const struct auth_serversupplied_info *session_info,
4470                                        struct messaging_context *msg_ctx,
4471                                        const char *servername,
4472                                        union spoolss_PrinterInfo **info,
4473                                        uint32_t *count)
4474 {
4475         DEBUG(4,("enum_all_printers_info_2\n"));
4476
4477         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4478                                             servername, 2, 0, info, count);
4479 }
4480
4481 /********************************************************************
4482  * handle enumeration of printers at level 1
4483  ********************************************************************/
4484
4485 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4486                                   const struct auth_serversupplied_info *session_info,
4487                                   struct messaging_context *msg_ctx,
4488                                   uint32_t flags,
4489                                   const char *servername,
4490                                   union spoolss_PrinterInfo **info,
4491                                   uint32_t *count)
4492 {
4493         /* Not all the flags are equals */
4494
4495         if (flags & PRINTER_ENUM_LOCAL) {
4496                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4497                                                       msg_ctx, servername, info, count);
4498         }
4499
4500         if (flags & PRINTER_ENUM_NAME) {
4501                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4502                                                      msg_ctx, servername, info,
4503                                                      count);
4504         }
4505
4506         if (flags & PRINTER_ENUM_NETWORK) {
4507                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4508                                                         msg_ctx, servername, info,
4509                                                         count);
4510         }
4511
4512         return WERR_OK; /* NT4sp5 does that */
4513 }
4514
4515 /********************************************************************
4516  * handle enumeration of printers at level 2
4517  ********************************************************************/
4518
4519 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4520                                   const struct auth_serversupplied_info *session_info,
4521                                   struct messaging_context *msg_ctx,
4522                                   uint32_t flags,
4523                                   const char *servername,
4524                                   union spoolss_PrinterInfo **info,
4525                                   uint32_t *count)
4526 {
4527         if (flags & PRINTER_ENUM_LOCAL) {
4528
4529                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4530                                                 servername,
4531                                                 info, count);
4532         }
4533
4534         if (flags & PRINTER_ENUM_NAME) {
4535                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4536                         return WERR_INVALID_NAME;
4537                 }
4538
4539                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4540                                                 servername,
4541                                                 info, count);
4542         }
4543
4544         if (flags & PRINTER_ENUM_REMOTE) {
4545                 return WERR_UNKNOWN_LEVEL;
4546         }
4547
4548         return WERR_OK;
4549 }
4550
4551 /********************************************************************
4552  * handle enumeration of printers at level 4
4553  ********************************************************************/
4554
4555 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4556                                   const struct auth_serversupplied_info *session_info,
4557                                   struct messaging_context *msg_ctx,
4558                                   uint32_t flags,
4559                                   const char *servername,
4560                                   union spoolss_PrinterInfo **info,
4561                                   uint32_t *count)
4562 {
4563         DEBUG(4,("enum_all_printers_info_4\n"));
4564
4565         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4566                                             servername, 4, flags, info, count);
4567 }
4568
4569
4570 /********************************************************************
4571  * handle enumeration of printers at level 5
4572  ********************************************************************/
4573
4574 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4575                                   const struct auth_serversupplied_info *session_info,
4576                                   struct messaging_context *msg_ctx,
4577                                   uint32_t flags,
4578                                   const char *servername,
4579                                   union spoolss_PrinterInfo **info,
4580                                   uint32_t *count)
4581 {
4582         DEBUG(4,("enum_all_printers_info_5\n"));
4583
4584         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4585                                             servername, 5, flags, info, count);
4586 }
4587
4588 /****************************************************************
4589  _spoolss_EnumPrinters
4590 ****************************************************************/
4591
4592 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4593                              struct spoolss_EnumPrinters *r)
4594 {
4595         const struct auth_serversupplied_info *session_info = get_session_info_system();
4596         WERROR result;
4597
4598         /* that's an [in out] buffer */
4599
4600         if (!r->in.buffer && (r->in.offered != 0)) {
4601                 return WERR_INVALID_PARAM;
4602         }
4603
4604         DEBUG(4,("_spoolss_EnumPrinters\n"));
4605
4606         *r->out.needed = 0;
4607         *r->out.count = 0;
4608         *r->out.info = NULL;
4609
4610         /*
4611          * Level 1:
4612          *          flags==PRINTER_ENUM_NAME
4613          *           if name=="" then enumerates all printers
4614          *           if name!="" then enumerate the printer
4615          *          flags==PRINTER_ENUM_REMOTE
4616          *          name is NULL, enumerate printers
4617          * Level 2: name!="" enumerates printers, name can't be NULL
4618          * Level 3: doesn't exist
4619          * Level 4: does a local registry lookup
4620          * Level 5: same as Level 2
4621          */
4622
4623         if (r->in.server && r->in.server[0] == '\0') {
4624                 r->in.server = NULL;
4625         }
4626
4627         switch (r->in.level) {
4628         case 0:
4629                 result = enumprinters_level0(p->mem_ctx, session_info,
4630                                              p->msg_ctx, r->in.flags,
4631                                              r->in.server,
4632                                              r->out.info, r->out.count);
4633                 break;
4634         case 1:
4635                 result = enumprinters_level1(p->mem_ctx, session_info,
4636                                              p->msg_ctx, r->in.flags,
4637                                              r->in.server,
4638                                              r->out.info, r->out.count);
4639                 break;
4640         case 2:
4641                 result = enumprinters_level2(p->mem_ctx, session_info,
4642                                              p->msg_ctx, r->in.flags,
4643                                              r->in.server,
4644                                              r->out.info, r->out.count);
4645                 break;
4646         case 4:
4647                 result = enumprinters_level4(p->mem_ctx, session_info,
4648                                              p->msg_ctx, r->in.flags,
4649                                              r->in.server,
4650                                              r->out.info, r->out.count);
4651                 break;
4652         case 5:
4653                 result = enumprinters_level5(p->mem_ctx, session_info,
4654                                              p->msg_ctx, r->in.flags,
4655                                              r->in.server,
4656                                              r->out.info, r->out.count);
4657                 break;
4658         default:
4659                 return WERR_UNKNOWN_LEVEL;
4660         }
4661
4662         if (!W_ERROR_IS_OK(result)) {
4663                 return result;
4664         }
4665
4666         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4667                                                      spoolss_EnumPrinters,
4668                                                      *r->out.info, r->in.level,
4669                                                      *r->out.count);
4670         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4671         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4672
4673         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4674 }
4675
4676 /****************************************************************
4677  _spoolss_GetPrinter
4678 ****************************************************************/
4679
4680 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4681                            struct spoolss_GetPrinter *r)
4682 {
4683         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4684         struct spoolss_PrinterInfo2 *info2 = NULL;
4685         WERROR result = WERR_OK;
4686         int snum;
4687
4688         /* that's an [in out] buffer */
4689
4690         if (!r->in.buffer && (r->in.offered != 0)) {
4691                 return WERR_INVALID_PARAM;
4692         }
4693
4694         *r->out.needed = 0;
4695
4696         if (Printer == NULL) {
4697                 return WERR_BADFID;
4698         }
4699
4700         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4701                 return WERR_BADFID;
4702         }
4703
4704         result = winreg_get_printer(p->mem_ctx,
4705                                     get_session_info_system(),
4706                                     p->msg_ctx,
4707                                     lp_const_servicename(snum),
4708                                     &info2);
4709         if (!W_ERROR_IS_OK(result)) {
4710                 goto out;
4711         }
4712
4713         switch (r->in.level) {
4714         case 0:
4715                 result = construct_printer_info0(p->mem_ctx,
4716                                                  get_session_info_system(),
4717                                                  p->msg_ctx,
4718                                                  info2,
4719                                                  Printer->servername,
4720                                                  &r->out.info->info0,
4721                                                  snum);
4722                 break;
4723         case 1:
4724                 result = construct_printer_info1(p->mem_ctx, info2,
4725                                                  PRINTER_ENUM_ICON8,
4726                                                  Printer->servername,
4727                                                  &r->out.info->info1, snum);
4728                 break;
4729         case 2:
4730                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4731                                                  Printer->servername,
4732                                                  &r->out.info->info2, snum);
4733                 break;
4734         case 3:
4735                 result = construct_printer_info3(p->mem_ctx, info2,
4736                                                  Printer->servername,
4737                                                  &r->out.info->info3, snum);
4738                 break;
4739         case 4:
4740                 result = construct_printer_info4(p->mem_ctx, info2,
4741                                                  Printer->servername,
4742                                                  &r->out.info->info4, snum);
4743                 break;
4744         case 5:
4745                 result = construct_printer_info5(p->mem_ctx, info2,
4746                                                  Printer->servername,
4747                                                  &r->out.info->info5, snum);
4748                 break;
4749         case 6:
4750                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4751                                                  Printer->servername,
4752                                                  &r->out.info->info6, snum);
4753                 break;
4754         case 7:
4755                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4756                                                  Printer->servername,
4757                                                  &r->out.info->info7, snum);
4758                 break;
4759         case 8:
4760                 result = construct_printer_info8(p->mem_ctx, info2,
4761                                                  Printer->servername,
4762                                                  &r->out.info->info8, snum);
4763                 break;
4764         default:
4765                 result = WERR_UNKNOWN_LEVEL;
4766                 break;
4767         }
4768
4769  out:
4770         if (!W_ERROR_IS_OK(result)) {
4771                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4772                           r->in.level, win_errstr(result)));
4773                 TALLOC_FREE(r->out.info);
4774                 return result;
4775         }
4776
4777         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4778                                                r->out.info, r->in.level);
4779         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4780
4781         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4782 }
4783
4784 /********************************************************************
4785  ********************************************************************/
4786
4787 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4788         do { \
4789                 if (in && strlen(in)) { \
4790                         out = talloc_strdup(mem_ctx, in); \
4791                 } else { \
4792                         out = talloc_strdup(mem_ctx, ""); \
4793                 } \
4794                 W_ERROR_HAVE_NO_MEMORY(out); \
4795         } while (0);
4796
4797 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4798         do { \
4799                 if (in && strlen(in)) { \
4800                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4801                 } else { \
4802                         out = talloc_strdup(mem_ctx, ""); \
4803                 } \
4804                 W_ERROR_HAVE_NO_MEMORY(out); \
4805         } while (0);
4806
4807 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4808                                                   const char **string_array,
4809                                                   const char ***presult,
4810                                                   const char *cservername,
4811                                                   const char *arch,
4812                                                   int version)
4813 {
4814         int i, num_strings = 0;
4815         const char **array = NULL;
4816
4817         if (string_array == NULL) {
4818                 return WERR_INVALID_PARAMETER;
4819         }
4820
4821         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4822                 const char *str = NULL;
4823
4824                 if (cservername == NULL || arch == NULL) {
4825                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4826                 } else {
4827                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4828                 }
4829
4830                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4831                         TALLOC_FREE(array);
4832                         return WERR_NOMEM;
4833                 }
4834         }
4835
4836         if (i > 0) {
4837                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4838                              &array, &num_strings);
4839         }
4840
4841         if (presult) {
4842                 *presult = array;
4843         }
4844
4845         return WERR_OK;
4846 }
4847
4848 /********************************************************************
4849  * fill a spoolss_DriverInfo1 struct
4850  ********************************************************************/
4851
4852 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4853                                         struct spoolss_DriverInfo1 *r,
4854                                         const struct spoolss_DriverInfo8 *driver,
4855                                         const char *servername)
4856 {
4857         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4858         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4859
4860         return WERR_OK;
4861 }
4862
4863 /********************************************************************
4864  * fill a spoolss_DriverInfo2 struct
4865  ********************************************************************/
4866
4867 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4868                                         struct spoolss_DriverInfo2 *r,
4869                                         const struct spoolss_DriverInfo8 *driver,
4870                                         const char *servername)
4871
4872 {
4873         const char *cservername = canon_servername(servername);
4874
4875         r->version              = driver->version;
4876
4877         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4878         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4879         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4880         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4881
4882         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4883                                driver->architecture,
4884                                driver->version,
4885                                driver->driver_path,
4886                                r->driver_path);
4887
4888         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4889                                driver->architecture,
4890                                driver->version,
4891                                driver->data_file,
4892                                r->data_file);
4893
4894         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4895                                driver->architecture,
4896                                driver->version,
4897                                driver->config_file,
4898                                r->config_file);
4899
4900         return WERR_OK;
4901 }
4902
4903 /********************************************************************
4904  * fill a spoolss_DriverInfo3 struct
4905  ********************************************************************/
4906
4907 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4908                                         struct spoolss_DriverInfo3 *r,
4909                                         const struct spoolss_DriverInfo8 *driver,
4910                                         const char *servername)
4911 {
4912         const char *cservername = canon_servername(servername);
4913
4914         r->version              = driver->version;
4915
4916         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4917         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4918         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4919         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4920
4921         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4922                                driver->architecture,
4923                                driver->version,
4924                                driver->driver_path,
4925                                r->driver_path);
4926
4927         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4928                                driver->architecture,
4929                                driver->version,
4930                                driver->data_file,
4931                                r->data_file);
4932
4933         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4934                                driver->architecture,
4935                                driver->version,
4936                                driver->config_file,
4937                                r->config_file);
4938
4939         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4940                                driver->architecture,
4941                                driver->version,
4942                                driver->help_file,
4943                                r->help_file);
4944
4945         FILL_DRIVER_STRING(mem_ctx,
4946                            driver->monitor_name,
4947                            r->monitor_name);
4948
4949         FILL_DRIVER_STRING(mem_ctx,
4950                            driver->default_datatype,
4951                            r->default_datatype);
4952
4953         return string_array_from_driver_info(mem_ctx,
4954                                              driver->dependent_files,
4955                                              &r->dependent_files,
4956                                              cservername,
4957                                              driver->architecture,
4958                                              driver->version);
4959 }
4960
4961 /********************************************************************
4962  * fill a spoolss_DriverInfo4 struct
4963  ********************************************************************/
4964
4965 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4966                                         struct spoolss_DriverInfo4 *r,
4967                                         const struct spoolss_DriverInfo8 *driver,
4968                                         const char *servername)
4969 {
4970         const char *cservername = canon_servername(servername);
4971         WERROR result;
4972
4973         r->version              = driver->version;
4974
4975         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4976         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4977         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4978         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4979
4980         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4981                                driver->architecture,
4982                                driver->version,
4983                                driver->driver_path,
4984                                r->driver_path);
4985
4986         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4987                                driver->architecture,
4988                                driver->version,
4989                                driver->data_file,
4990                                r->data_file);
4991
4992         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4993                                driver->architecture,
4994                                driver->version,
4995                                driver->config_file,
4996                                r->config_file);
4997
4998         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4999                                driver->architecture,
5000                                driver->version,
5001                                driver->help_file,
5002                                r->help_file);
5003
5004         result = string_array_from_driver_info(mem_ctx,
5005                                                driver->dependent_files,
5006                                                &r->dependent_files,
5007                                                cservername,
5008                                                driver->architecture,
5009                                                driver->version);
5010         if (!W_ERROR_IS_OK(result)) {
5011                 return result;
5012         }
5013
5014         FILL_DRIVER_STRING(mem_ctx,
5015                            driver->monitor_name,
5016                            r->monitor_name);
5017
5018         FILL_DRIVER_STRING(mem_ctx,
5019                            driver->default_datatype,
5020                            r->default_datatype);
5021
5022
5023         result = string_array_from_driver_info(mem_ctx,
5024                                                driver->previous_names,
5025                                                &r->previous_names,
5026                                                NULL, NULL, 0);
5027
5028         return result;
5029 }
5030
5031 /********************************************************************
5032  * fill a spoolss_DriverInfo5 struct
5033  ********************************************************************/
5034
5035 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5036                                         struct spoolss_DriverInfo5 *r,
5037                                         const struct spoolss_DriverInfo8 *driver,
5038                                         const char *servername)
5039 {
5040         const char *cservername = canon_servername(servername);
5041
5042         r->version              = driver->version;
5043
5044         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5045         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5046         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5047         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5048
5049         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5050                                driver->architecture,
5051                                driver->version,
5052                                driver->driver_path,
5053                                r->driver_path);
5054
5055         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5056                                driver->architecture,
5057                                driver->version,
5058                                driver->data_file,
5059                                r->data_file);
5060
5061         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5062                                driver->architecture,
5063                                driver->version,
5064                                driver->config_file,
5065                                r->config_file);
5066
5067         r->driver_attributes    = 0;
5068         r->config_version       = 0;
5069         r->driver_version       = 0;
5070
5071         return WERR_OK;
5072 }
5073 /********************************************************************
5074  * fill a spoolss_DriverInfo6 struct
5075  ********************************************************************/
5076
5077 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5078                                         struct spoolss_DriverInfo6 *r,
5079                                         const struct spoolss_DriverInfo8 *driver,
5080                                         const char *servername)
5081 {
5082         const char *cservername = canon_servername(servername);
5083         WERROR result;
5084
5085         r->version              = driver->version;
5086
5087         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5088         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5089         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5090         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5091
5092         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5093                                driver->architecture,
5094                                driver->version,
5095                                driver->driver_path,
5096                                r->driver_path);
5097
5098         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5099                                driver->architecture,
5100                                driver->version,
5101                                driver->data_file,
5102                                r->data_file);
5103
5104         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5105                                driver->architecture,
5106                                driver->version,
5107                                driver->config_file,
5108                                r->config_file);
5109
5110         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5111                                driver->architecture,
5112                                driver->version,
5113                                driver->help_file,
5114                                r->help_file);
5115
5116         FILL_DRIVER_STRING(mem_ctx,
5117                            driver->monitor_name,
5118                            r->monitor_name);
5119
5120         FILL_DRIVER_STRING(mem_ctx,
5121                            driver->default_datatype,
5122                            r->default_datatype);
5123
5124         result = string_array_from_driver_info(mem_ctx,
5125                                                driver->dependent_files,
5126                                                &r->dependent_files,
5127                                                cservername,
5128                                                driver->architecture,
5129                                                driver->version);
5130         if (!W_ERROR_IS_OK(result)) {
5131                 return result;
5132         }
5133
5134         result = string_array_from_driver_info(mem_ctx,
5135                                                driver->previous_names,
5136                                                &r->previous_names,
5137                                                NULL, NULL, 0);
5138         if (!W_ERROR_IS_OK(result)) {
5139                 return result;
5140         }
5141
5142         r->driver_date          = driver->driver_date;
5143         r->driver_version       = driver->driver_version;
5144
5145         FILL_DRIVER_STRING(mem_ctx,
5146                            driver->manufacturer_name,
5147                            r->manufacturer_name);
5148         FILL_DRIVER_STRING(mem_ctx,
5149                            driver->manufacturer_url,
5150                            r->manufacturer_url);
5151         FILL_DRIVER_STRING(mem_ctx,
5152                            driver->hardware_id,
5153                            r->hardware_id);
5154         FILL_DRIVER_STRING(mem_ctx,
5155                            driver->provider,
5156                            r->provider);
5157
5158         return WERR_OK;
5159 }
5160
5161 /********************************************************************
5162  * fill a spoolss_DriverInfo8 struct
5163  ********************************************************************/
5164
5165 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5166                                         struct spoolss_DriverInfo8 *r,
5167                                         const struct spoolss_DriverInfo8 *driver,
5168                                         const char *servername)
5169 {
5170         const char *cservername = canon_servername(servername);
5171         WERROR result;
5172
5173         r->version              = driver->version;
5174
5175         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5176         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5177         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5178         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5179
5180         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5181                                driver->architecture,
5182                                driver->version,
5183                                driver->driver_path,
5184                                r->driver_path);
5185
5186         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5187                                driver->architecture,
5188                                driver->version,
5189                                driver->data_file,
5190                                r->data_file);
5191
5192         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5193                                driver->architecture,
5194                                driver->version,
5195                                driver->config_file,
5196                                r->config_file);
5197
5198         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5199                                driver->architecture,
5200                                driver->version,
5201                                driver->help_file,
5202                                r->help_file);
5203
5204         FILL_DRIVER_STRING(mem_ctx,
5205                            driver->monitor_name,
5206                            r->monitor_name);
5207
5208         FILL_DRIVER_STRING(mem_ctx,
5209                            driver->default_datatype,
5210                            r->default_datatype);
5211
5212         result = string_array_from_driver_info(mem_ctx,
5213                                                driver->dependent_files,
5214                                                &r->dependent_files,
5215                                                cservername,
5216                                                driver->architecture,
5217                                                driver->version);
5218         if (!W_ERROR_IS_OK(result)) {
5219                 return result;
5220         }
5221
5222         result = string_array_from_driver_info(mem_ctx,
5223                                                driver->previous_names,
5224                                                &r->previous_names,
5225                                                NULL, NULL, 0);
5226         if (!W_ERROR_IS_OK(result)) {
5227                 return result;
5228         }
5229
5230         r->driver_date          = driver->driver_date;
5231         r->driver_version       = driver->driver_version;
5232
5233         FILL_DRIVER_STRING(mem_ctx,
5234                            driver->manufacturer_name,
5235                            r->manufacturer_name);
5236         FILL_DRIVER_STRING(mem_ctx,
5237                            driver->manufacturer_url,
5238                            r->manufacturer_url);
5239         FILL_DRIVER_STRING(mem_ctx,
5240                            driver->hardware_id,
5241                            r->hardware_id);
5242         FILL_DRIVER_STRING(mem_ctx,
5243                            driver->provider,
5244                            r->provider);
5245
5246         FILL_DRIVER_STRING(mem_ctx,
5247                            driver->print_processor,
5248                            r->print_processor);
5249         FILL_DRIVER_STRING(mem_ctx,
5250                            driver->vendor_setup,
5251                            r->vendor_setup);
5252
5253         result = string_array_from_driver_info(mem_ctx,
5254                                                driver->color_profiles,
5255                                                &r->color_profiles,
5256                                                NULL, NULL, 0);
5257         if (!W_ERROR_IS_OK(result)) {
5258                 return result;
5259         }
5260
5261         FILL_DRIVER_STRING(mem_ctx,
5262                            driver->inf_path,
5263                            r->inf_path);
5264
5265         r->printer_driver_attributes    = driver->printer_driver_attributes;
5266
5267         result = string_array_from_driver_info(mem_ctx,
5268                                                driver->core_driver_dependencies,
5269                                                &r->core_driver_dependencies,
5270                                                NULL, NULL, 0);
5271         if (!W_ERROR_IS_OK(result)) {
5272                 return result;
5273         }
5274
5275         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5276         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5277
5278         return WERR_OK;
5279 }
5280
5281 #if 0 /* disabled until marshalling issues are resolved - gd */
5282 /********************************************************************
5283  ********************************************************************/
5284
5285 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5286                                           struct spoolss_DriverFileInfo *r,
5287                                           const char *cservername,
5288                                           const char *file_name,
5289                                           enum spoolss_DriverFileType file_type,
5290                                           uint32_t file_version)
5291 {
5292         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5293                                           cservername, file_name);
5294         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5295         r->file_type    = file_type;
5296         r->file_version = file_version;
5297
5298         return WERR_OK;
5299 }
5300
5301 /********************************************************************
5302  ********************************************************************/
5303
5304 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5305                                                  const struct spoolss_DriverInfo8 *driver,
5306                                                  const char *cservername,
5307                                                  struct spoolss_DriverFileInfo **info_p,
5308                                                  uint32_t *count_p)
5309 {
5310         struct spoolss_DriverFileInfo *info = NULL;
5311         uint32_t count = 0;
5312         WERROR result;
5313         uint32_t i;
5314
5315         *info_p = NULL;
5316         *count_p = 0;
5317
5318         if (strlen(driver->driver_path)) {
5319                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5320                                             struct spoolss_DriverFileInfo,
5321                                             count + 1);
5322                 W_ERROR_HAVE_NO_MEMORY(info);
5323                 result = fill_spoolss_DriverFileInfo(info,
5324                                                      &info[count],
5325                                                      cservername,
5326                                                      driver->driver_path,
5327                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5328                                                      0);
5329                 W_ERROR_NOT_OK_RETURN(result);
5330                 count++;
5331         }
5332
5333         if (strlen(driver->config_file)) {
5334                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5335                                             struct spoolss_DriverFileInfo,
5336                                             count + 1);
5337                 W_ERROR_HAVE_NO_MEMORY(info);
5338                 result = fill_spoolss_DriverFileInfo(info,
5339                                                      &info[count],
5340                                                      cservername,
5341                                                      driver->config_file,
5342                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5343                                                      0);
5344                 W_ERROR_NOT_OK_RETURN(result);
5345                 count++;
5346         }
5347
5348         if (strlen(driver->data_file)) {
5349                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5350                                             struct spoolss_DriverFileInfo,
5351                                             count + 1);
5352                 W_ERROR_HAVE_NO_MEMORY(info);
5353                 result = fill_spoolss_DriverFileInfo(info,
5354                                                      &info[count],
5355                                                      cservername,
5356                                                      driver->data_file,
5357                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5358                                                      0);
5359                 W_ERROR_NOT_OK_RETURN(result);
5360                 count++;
5361         }
5362
5363         if (strlen(driver->help_file)) {
5364                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5365                                             struct spoolss_DriverFileInfo,
5366                                             count + 1);
5367                 W_ERROR_HAVE_NO_MEMORY(info);
5368                 result = fill_spoolss_DriverFileInfo(info,
5369                                                      &info[count],
5370                                                      cservername,
5371                                                      driver->help_file,
5372                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5373                                                      0);
5374                 W_ERROR_NOT_OK_RETURN(result);
5375                 count++;
5376         }
5377
5378         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5379                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5380                                             struct spoolss_DriverFileInfo,
5381                                             count + 1);
5382                 W_ERROR_HAVE_NO_MEMORY(info);
5383                 result = fill_spoolss_DriverFileInfo(info,
5384                                                      &info[count],
5385                                                      cservername,
5386                                                      driver->dependent_files[i],
5387                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5388                                                      0);
5389                 W_ERROR_NOT_OK_RETURN(result);
5390                 count++;
5391         }
5392
5393         *info_p = info;
5394         *count_p = count;
5395
5396         return WERR_OK;
5397 }
5398
5399 /********************************************************************
5400  * fill a spoolss_DriverInfo101 struct
5401  ********************************************************************/
5402
5403 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5404                                           struct spoolss_DriverInfo101 *r,
5405                                           const struct spoolss_DriverInfo8 *driver,
5406                                           const char *servername)
5407 {
5408         const char *cservername = canon_servername(servername);
5409         WERROR result;
5410
5411         r->version              = driver->version;
5412
5413         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5414         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5415         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5416         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5417
5418         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5419                                                     cservername,
5420                                                     &r->file_info,
5421                                                     &r->file_count);
5422         if (!W_ERROR_IS_OK(result)) {
5423                 return result;
5424         }
5425
5426         FILL_DRIVER_STRING(mem_ctx,
5427                            driver->monitor_name,
5428                            r->monitor_name);
5429
5430         FILL_DRIVER_STRING(mem_ctx,
5431                            driver->default_datatype,
5432                            r->default_datatype);
5433
5434         result = string_array_from_driver_info(mem_ctx,
5435                                                driver->previous_names,
5436                                                &r->previous_names,
5437                                                NULL, NULL, 0);
5438         if (!W_ERROR_IS_OK(result)) {
5439                 return result;
5440         }
5441
5442         r->driver_date          = driver->driver_date;
5443         r->driver_version       = driver->driver_version;
5444
5445         FILL_DRIVER_STRING(mem_ctx,
5446                            driver->manufacturer_name,
5447                            r->manufacturer_name);
5448         FILL_DRIVER_STRING(mem_ctx,
5449                            driver->manufacturer_url,
5450                            r->manufacturer_url);
5451         FILL_DRIVER_STRING(mem_ctx,
5452                            driver->hardware_id,
5453                            r->hardware_id);
5454         FILL_DRIVER_STRING(mem_ctx,
5455                            driver->provider,
5456                            r->provider);
5457
5458         return WERR_OK;
5459 }
5460 #endif
5461 /********************************************************************
5462  ********************************************************************/
5463
5464 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5465                                                   const struct auth_serversupplied_info *session_info,
5466                                                   struct messaging_context *msg_ctx,
5467                                                   uint32_t level,
5468                                                   union spoolss_DriverInfo *r,
5469                                                   int snum,
5470                                                   const char *servername,
5471                                                   const char *architecture,
5472                                                   uint32_t version)
5473 {
5474         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5475         struct spoolss_DriverInfo8 *driver;
5476         WERROR result;
5477
5478         if (level == 101) {
5479                 return WERR_UNKNOWN_LEVEL;
5480         }
5481
5482         result = winreg_get_printer(mem_ctx,
5483                                     session_info,
5484                                     msg_ctx,
5485                                     lp_const_servicename(snum),
5486                                     &pinfo2);
5487
5488         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5489                 win_errstr(result)));
5490
5491         if (!W_ERROR_IS_OK(result)) {
5492                 return WERR_INVALID_PRINTER_NAME;
5493         }
5494
5495         result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5496                                    architecture,
5497                                    pinfo2->drivername, version, &driver);
5498
5499         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5500                 win_errstr(result)));
5501
5502         if (!W_ERROR_IS_OK(result)) {
5503                 /*
5504                  * Is this a W2k client ?
5505                  */
5506
5507                 if (version < 3) {
5508                         talloc_free(pinfo2);
5509                         return WERR_UNKNOWN_PRINTER_DRIVER;
5510                 }
5511
5512                 /* Yes - try again with a WinNT driver. */
5513                 version = 2;
5514                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5515                                            architecture,
5516                                            pinfo2->drivername,
5517                                            version, &driver);
5518                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5519                         win_errstr(result)));
5520                 if (!W_ERROR_IS_OK(result)) {
5521                         talloc_free(pinfo2);
5522                         return WERR_UNKNOWN_PRINTER_DRIVER;
5523                 }
5524         }
5525
5526         switch (level) {
5527         case 1:
5528                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5529                 break;
5530         case 2:
5531                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5532                 break;
5533         case 3:
5534                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5535                 break;
5536         case 4:
5537                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5538                 break;
5539         case 5:
5540                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5541                 break;
5542         case 6:
5543                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5544                 break;
5545         case 8:
5546                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5547                 break;
5548 #if 0 /* disabled until marshalling issues are resolved - gd */
5549         case 101:
5550                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5551                 break;
5552 #endif
5553         default:
5554                 result = WERR_UNKNOWN_LEVEL;
5555                 break;
5556         }
5557
5558         talloc_free(pinfo2);
5559         talloc_free(driver);
5560
5561         return result;
5562 }
5563
5564 /****************************************************************
5565  _spoolss_GetPrinterDriver2
5566 ****************************************************************/
5567
5568 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5569                                   struct spoolss_GetPrinterDriver2 *r)
5570 {
5571         struct printer_handle *printer;
5572         WERROR result;
5573
5574         int snum;
5575
5576         /* that's an [in out] buffer */
5577
5578         if (!r->in.buffer && (r->in.offered != 0)) {
5579                 return WERR_INVALID_PARAM;
5580         }
5581
5582         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5583
5584         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5585                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5586                 return WERR_INVALID_PRINTER_NAME;
5587         }
5588
5589         *r->out.needed = 0;
5590         *r->out.server_major_version = 0;
5591         *r->out.server_minor_version = 0;
5592
5593         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5594                 return WERR_BADFID;
5595         }
5596
5597         result = construct_printer_driver_info_level(p->mem_ctx,
5598                                                      get_session_info_system(),
5599                                                      p->msg_ctx,
5600                                                      r->in.level, r->out.info,
5601                                                      snum, printer->servername,
5602                                                      r->in.architecture,
5603                                                      r->in.client_major_version);
5604         if (!W_ERROR_IS_OK(result)) {
5605                 TALLOC_FREE(r->out.info);
5606                 return result;
5607         }
5608
5609         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5610                                                r->out.info, r->in.level);
5611         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5612
5613         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5614 }
5615
5616
5617 /****************************************************************
5618  _spoolss_StartPagePrinter
5619 ****************************************************************/
5620
5621 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5622                                  struct spoolss_StartPagePrinter *r)
5623 {
5624         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5625
5626         if (!Printer) {
5627                 DEBUG(3,("_spoolss_StartPagePrinter: "
5628                         "Error in startpageprinter printer handle\n"));
5629                 return WERR_BADFID;
5630         }
5631
5632         Printer->page_started = true;
5633         return WERR_OK;
5634 }
5635
5636 /****************************************************************
5637  _spoolss_EndPagePrinter
5638 ****************************************************************/
5639
5640 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5641                                struct spoolss_EndPagePrinter *r)
5642 {
5643         int snum;
5644
5645         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5646
5647         if (!Printer) {
5648                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5649                         OUR_HANDLE(r->in.handle)));
5650                 return WERR_BADFID;
5651         }
5652
5653         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5654                 return WERR_BADFID;
5655
5656         Printer->page_started = false;
5657         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5658
5659         return WERR_OK;
5660 }
5661
5662 /****************************************************************
5663  _spoolss_StartDocPrinter
5664 ****************************************************************/
5665
5666 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5667                                 struct spoolss_StartDocPrinter *r)
5668 {
5669         struct spoolss_DocumentInfo1 *info_1;
5670         int snum;
5671         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5672         WERROR werr;
5673
5674         if (!Printer) {
5675                 DEBUG(2,("_spoolss_StartDocPrinter: "
5676                         "Invalid handle (%s:%u:%u)\n",
5677                         OUR_HANDLE(r->in.handle)));
5678                 return WERR_BADFID;
5679         }
5680
5681         if (Printer->jobid) {
5682                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5683                           "StartDocPrinter called twice! "
5684                           "(existing jobid = %d)\n", Printer->jobid));
5685                 return WERR_INVALID_HANDLE;
5686         }
5687
5688         if (r->in.level != 1) {
5689                 return WERR_UNKNOWN_LEVEL;
5690         }
5691
5692         info_1 = r->in.info.info1;
5693
5694         /*
5695          * a nice thing with NT is it doesn't listen to what you tell it.
5696          * when asked to send _only_ RAW datas, it tries to send datas
5697          * in EMF format.
5698          *
5699          * So I add checks like in NT Server ...
5700          */
5701
5702         if (info_1->datatype) {
5703                 if (strcmp(info_1->datatype, "RAW") != 0) {
5704                         *r->out.job_id = 0;
5705                         return WERR_INVALID_DATATYPE;
5706                 }
5707         }
5708
5709         /* get the share number of the printer */
5710         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5711                 return WERR_BADFID;
5712         }
5713
5714         werr = print_job_start(p->session_info,
5715                                p->msg_ctx,
5716                                p->client_id->name,
5717                                snum,
5718                                info_1->document_name,
5719                                info_1->output_file,
5720                                Printer->devmode,
5721                                &Printer->jobid);
5722
5723         /* An error occured in print_job_start() so return an appropriate
5724            NT error code. */
5725
5726         if (!W_ERROR_IS_OK(werr)) {
5727                 return werr;
5728         }
5729
5730         Printer->document_started = true;
5731         *r->out.job_id = Printer->jobid;
5732
5733         return WERR_OK;
5734 }
5735
5736 /****************************************************************
5737  _spoolss_EndDocPrinter
5738 ****************************************************************/
5739
5740 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5741                               struct spoolss_EndDocPrinter *r)
5742 {
5743         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5744         NTSTATUS status;
5745         int snum;
5746
5747         if (!Printer) {
5748                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5749                         OUR_HANDLE(r->in.handle)));
5750                 return WERR_BADFID;
5751         }
5752
5753         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5754                 return WERR_BADFID;
5755         }
5756
5757         Printer->document_started = false;
5758         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5759         if (!NT_STATUS_IS_OK(status)) {
5760                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5761                           "print_job_end failed [%s]\n",
5762                           nt_errstr(status)));
5763         }
5764
5765         Printer->jobid = 0;
5766         return ntstatus_to_werror(status);
5767 }
5768
5769 /****************************************************************
5770  _spoolss_WritePrinter
5771 ****************************************************************/
5772
5773 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5774                              struct spoolss_WritePrinter *r)
5775 {
5776         ssize_t buffer_written;
5777         int snum;
5778         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5779
5780         if (!Printer) {
5781                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5782                         OUR_HANDLE(r->in.handle)));
5783                 *r->out.num_written = r->in._data_size;
5784                 return WERR_BADFID;
5785         }
5786
5787         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5788                 return WERR_BADFID;
5789
5790         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5791         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5792                                                    snum, Printer->jobid,
5793                                                    (const char *)r->in.data.data,
5794                                                    (size_t)r->in._data_size);
5795         if (buffer_written == (ssize_t)-1) {
5796                 *r->out.num_written = 0;
5797                 if (errno == ENOSPC)
5798                         return WERR_NO_SPOOL_SPACE;
5799                 else
5800                         return WERR_ACCESS_DENIED;
5801         }
5802
5803         *r->out.num_written = r->in._data_size;
5804
5805         return WERR_OK;
5806 }
5807
5808 /********************************************************************
5809  * api_spoolss_getprinter
5810  * called from the spoolss dispatcher
5811  *
5812  ********************************************************************/
5813
5814 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5815                               struct pipes_struct *p)
5816 {
5817         const struct auth_serversupplied_info *session_info = p->session_info;
5818         int snum;
5819         WERROR errcode = WERR_BADFUNC;
5820         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5821
5822         if (!Printer) {
5823                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5824                         OUR_HANDLE(handle)));
5825                 return WERR_BADFID;
5826         }
5827
5828         if (!get_printer_snum(p, handle, &snum, NULL))
5829                 return WERR_BADFID;
5830
5831         switch (command) {
5832         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5833                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5834                 break;
5835         case SPOOLSS_PRINTER_CONTROL_RESUME:
5836         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5837                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5838                 break;
5839         case SPOOLSS_PRINTER_CONTROL_PURGE:
5840                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5841                 break;
5842         default:
5843                 return WERR_UNKNOWN_LEVEL;
5844         }
5845
5846         return errcode;
5847 }
5848
5849
5850 /****************************************************************
5851  _spoolss_AbortPrinter
5852  * From MSDN: "Deletes printer's spool file if printer is configured
5853  * for spooling"
5854 ****************************************************************/
5855
5856 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5857                              struct spoolss_AbortPrinter *r)
5858 {
5859         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5860         int             snum;
5861         WERROR          errcode = WERR_OK;
5862
5863         if (!Printer) {
5864                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5865                         OUR_HANDLE(r->in.handle)));
5866                 return WERR_BADFID;
5867         }
5868
5869         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5870                 return WERR_BADFID;
5871
5872         if (!Printer->document_started) {
5873                 return WERR_SPL_NO_STARTDOC;
5874         }
5875
5876         errcode = print_job_delete(p->session_info,
5877                                    p->msg_ctx,
5878                                    snum,
5879                                    Printer->jobid);
5880
5881         return errcode;
5882 }
5883
5884 /********************************************************************
5885  * called by spoolss_api_setprinter
5886  * when updating a printer description
5887  ********************************************************************/
5888
5889 static WERROR update_printer_sec(struct policy_handle *handle,
5890                                  struct pipes_struct *p,
5891                                  struct sec_desc_buf *secdesc_ctr)
5892 {
5893         struct spoolss_security_descriptor *new_secdesc = NULL;
5894         struct spoolss_security_descriptor *old_secdesc = NULL;
5895         const char *printer;
5896         WERROR result;
5897         int snum;
5898
5899         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5900
5901         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5902                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5903                          OUR_HANDLE(handle)));
5904
5905                 result = WERR_BADFID;
5906                 goto done;
5907         }
5908
5909         if (secdesc_ctr == NULL) {
5910                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5911                 result = WERR_INVALID_PARAM;
5912                 goto done;
5913         }
5914         printer = lp_const_servicename(snum);
5915
5916         /* Check the user has permissions to change the security
5917            descriptor.  By experimentation with two NT machines, the user
5918            requires Full Access to the printer to change security
5919            information. */
5920
5921         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5922                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5923                 result = WERR_ACCESS_DENIED;
5924                 goto done;
5925         }
5926
5927         /* NT seems to like setting the security descriptor even though
5928            nothing may have actually changed. */
5929         result = winreg_get_printer_secdesc(p->mem_ctx,
5930                                             get_session_info_system(),
5931                                             p->msg_ctx,
5932                                             printer,
5933                                             &old_secdesc);
5934         if (!W_ERROR_IS_OK(result)) {
5935                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5936                 result = WERR_BADFID;
5937                 goto done;
5938         }
5939
5940         if (DEBUGLEVEL >= 10) {
5941                 struct security_acl *the_acl;
5942                 int i;
5943
5944                 the_acl = old_secdesc->dacl;
5945                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5946                            printer, the_acl->num_aces));
5947
5948                 for (i = 0; i < the_acl->num_aces; i++) {
5949                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5950                                            &the_acl->aces[i].trustee),
5951                                   the_acl->aces[i].access_mask));
5952                 }
5953
5954                 the_acl = secdesc_ctr->sd->dacl;
5955
5956                 if (the_acl) {
5957                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5958                                    printer, the_acl->num_aces));
5959
5960                         for (i = 0; i < the_acl->num_aces; i++) {
5961                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5962                                                    &the_acl->aces[i].trustee),
5963                                            the_acl->aces[i].access_mask));
5964                         }
5965                 } else {
5966                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5967                 }
5968         }
5969
5970         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5971         if (new_secdesc == NULL) {
5972                 result = WERR_NOMEM;
5973                 goto done;
5974         }
5975
5976         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5977                 result = WERR_OK;
5978                 goto done;
5979         }
5980
5981         result = winreg_set_printer_secdesc(p->mem_ctx,
5982                                             get_session_info_system(),
5983                                             p->msg_ctx,
5984                                             printer,
5985                                             new_secdesc);
5986
5987  done:
5988         return result;
5989 }
5990
5991 /********************************************************************
5992  Canonicalize printer info from a client
5993  ********************************************************************/
5994
5995 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5996                              struct spoolss_SetPrinterInfo2 *info2,
5997                              int snum)
5998 {
5999         fstring printername;
6000         const char *p;
6001
6002         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6003                 "portname=%s drivername=%s comment=%s location=%s\n",
6004                 info2->servername, info2->printername, info2->sharename,
6005                 info2->portname, info2->drivername, info2->comment,
6006                 info2->location));
6007
6008         /* we force some elements to "correct" values */
6009         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6010         if (info2->servername == NULL) {
6011                 return false;
6012         }
6013         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6014         if (info2->sharename == NULL) {
6015                 return false;
6016         }
6017
6018         /* check to see if we allow printername != sharename */
6019         if (lp_force_printername(snum)) {
6020                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6021                                         global_myname(), info2->sharename);
6022         } else {
6023                 /* make sure printername is in \\server\printername format */
6024                 fstrcpy(printername, info2->printername);
6025                 p = printername;
6026                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6027                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6028                                 p++;
6029                 }
6030
6031                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6032                                         global_myname(), p);
6033         }
6034         if (info2->printername == NULL) {
6035                 return false;
6036         }
6037
6038         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6039         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6040
6041         return true;
6042 }
6043
6044 /****************************************************************************
6045 ****************************************************************************/
6046
6047 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6048 {
6049         char *cmd = lp_addport_cmd();
6050         char *command = NULL;
6051         int ret;
6052         bool is_print_op = false;
6053
6054         if ( !*cmd ) {
6055                 return WERR_ACCESS_DENIED;
6056         }
6057
6058         command = talloc_asprintf(ctx,
6059                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6060         if (!command) {
6061                 return WERR_NOMEM;
6062         }
6063
6064         if ( token )
6065                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6066
6067         DEBUG(10,("Running [%s]\n", command));
6068
6069         /********* BEGIN SePrintOperatorPrivilege **********/
6070
6071         if ( is_print_op )
6072                 become_root();
6073
6074         ret = smbrun(command, NULL);
6075
6076         if ( is_print_op )
6077                 unbecome_root();
6078
6079         /********* END SePrintOperatorPrivilege **********/
6080
6081         DEBUGADD(10,("returned [%d]\n", ret));
6082
6083         TALLOC_FREE(command);
6084
6085         if ( ret != 0 ) {
6086                 return WERR_ACCESS_DENIED;
6087         }
6088
6089         return WERR_OK;
6090 }
6091
6092 /****************************************************************************
6093 ****************************************************************************/
6094
6095 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6096                              struct spoolss_SetPrinterInfo2 *info2,
6097                              const char *remote_machine,
6098                              struct messaging_context *msg_ctx)
6099 {
6100         char *cmd = lp_addprinter_cmd();
6101         char **qlines;
6102         char *command = NULL;
6103         int numlines;
6104         int ret;
6105         int fd;
6106         bool is_print_op = false;
6107
6108         if (!remote_machine) {
6109                 return false;
6110         }
6111
6112         command = talloc_asprintf(ctx,
6113                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6114                         cmd, info2->printername, info2->sharename,
6115                         info2->portname, info2->drivername,
6116                         info2->location, info2->comment, remote_machine);
6117         if (!command) {
6118                 return false;
6119         }
6120
6121         if ( token )
6122                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6123
6124         DEBUG(10,("Running [%s]\n", command));
6125
6126         /********* BEGIN SePrintOperatorPrivilege **********/
6127
6128         if ( is_print_op )
6129                 become_root();
6130
6131         if ( (ret = smbrun(command, &fd)) == 0 ) {
6132                 /* Tell everyone we updated smb.conf. */
6133                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6134         }
6135
6136         if ( is_print_op )
6137                 unbecome_root();
6138
6139         /********* END SePrintOperatorPrivilege **********/
6140
6141         DEBUGADD(10,("returned [%d]\n", ret));
6142
6143         TALLOC_FREE(command);
6144
6145         if ( ret != 0 ) {
6146                 if (fd != -1)
6147                         close(fd);
6148                 return false;
6149         }
6150
6151         /* reload our services immediately */
6152         become_root();
6153         reload_services(msg_ctx, -1, false);
6154         unbecome_root();
6155
6156         numlines = 0;
6157         /* Get lines and convert them back to dos-codepage */
6158         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6159         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6160         close(fd);
6161
6162         /* Set the portname to what the script says the portname should be. */
6163         /* but don't require anything to be return from the script exit a good error code */
6164
6165         if (numlines) {
6166                 /* Set the portname to what the script says the portname should be. */
6167                 info2->portname = talloc_strdup(ctx, qlines[0]);
6168                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6169         }
6170
6171         TALLOC_FREE(qlines);
6172         return true;
6173 }
6174
6175 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6176                                const struct auth_serversupplied_info *session_info,
6177                                struct messaging_context *msg_ctx,
6178                                int snum,
6179                                struct spoolss_SetPrinterInfo2 *printer,
6180                                struct spoolss_PrinterInfo2 *old_printer)
6181 {
6182         bool force_update = (old_printer == NULL);
6183         const char *dnsdomname;
6184         const char *longname;
6185         const char *uncname;
6186         const char *spooling;
6187         DATA_BLOB buffer;
6188         WERROR result = WERR_OK;
6189
6190         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6191                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6192                 winreg_set_printer_dataex(mem_ctx,
6193                                           session_info,
6194                                           msg_ctx,
6195                                           printer->sharename,
6196                                           SPOOL_DSSPOOLER_KEY,
6197                                           SPOOL_REG_DRIVERNAME,
6198                                           REG_SZ,
6199                                           buffer.data,
6200                                           buffer.length);
6201
6202                 if (!force_update) {
6203                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6204                                 printer->drivername));
6205
6206                         notify_printer_driver(server_event_context(), msg_ctx,
6207                                               snum, printer->drivername ?
6208                                               printer->drivername : "");
6209                 }
6210         }
6211
6212         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6213                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6214                 winreg_set_printer_dataex(mem_ctx,
6215                                           session_info,
6216                                           msg_ctx,
6217                                           printer->sharename,
6218                                           SPOOL_DSSPOOLER_KEY,
6219                                           SPOOL_REG_DESCRIPTION,
6220                                           REG_SZ,
6221                                           buffer.data,
6222                                           buffer.length);
6223
6224                 if (!force_update) {
6225                         notify_printer_comment(server_event_context(), msg_ctx,
6226                                                snum, printer->comment ?
6227                                                printer->comment : "");
6228                 }
6229         }
6230
6231         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6232                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6233                 winreg_set_printer_dataex(mem_ctx,
6234                                           session_info,
6235                                           msg_ctx,
6236                                           printer->sharename,
6237                                           SPOOL_DSSPOOLER_KEY,
6238                                           SPOOL_REG_PRINTSHARENAME,
6239                                           REG_SZ,
6240                                           buffer.data,
6241                                           buffer.length);
6242
6243                 if (!force_update) {
6244                         notify_printer_sharename(server_event_context(),
6245                                                  msg_ctx,
6246                                                  snum, printer->sharename ?
6247                                                  printer->sharename : "");
6248                 }
6249         }
6250
6251         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6252                 const char *p;
6253
6254                 p = strrchr(printer->printername, '\\' );
6255                 if (p != NULL) {
6256                         p++;
6257                 } else {
6258                         p = printer->printername;
6259                 }
6260
6261                 push_reg_sz(mem_ctx, &buffer, p);
6262                 winreg_set_printer_dataex(mem_ctx,
6263                                           session_info,
6264                                           msg_ctx,
6265                                           printer->sharename,
6266                                           SPOOL_DSSPOOLER_KEY,
6267                                           SPOOL_REG_PRINTERNAME,
6268                                           REG_SZ,
6269                                           buffer.data,
6270                                           buffer.length);
6271
6272                 if (!force_update) {
6273                         notify_printer_printername(server_event_context(),
6274                                                    msg_ctx, snum, p ? p : "");
6275                 }
6276         }
6277
6278         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6279                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6280                 winreg_set_printer_dataex(mem_ctx,
6281                                           session_info,
6282                                           msg_ctx,
6283                                           printer->sharename,
6284                                           SPOOL_DSSPOOLER_KEY,
6285                                           SPOOL_REG_PORTNAME,
6286                                           REG_SZ,
6287                                           buffer.data,
6288                                           buffer.length);
6289
6290                 if (!force_update) {
6291                         notify_printer_port(server_event_context(),
6292                                             msg_ctx, snum, printer->portname ?
6293                                             printer->portname : "");
6294                 }
6295         }
6296
6297         if (force_update || !strequal(printer->location, old_printer->location)) {
6298                 push_reg_sz(mem_ctx, &buffer, printer->location);
6299                 winreg_set_printer_dataex(mem_ctx,
6300                                           session_info,
6301                                           msg_ctx,
6302                                           printer->sharename,
6303                                           SPOOL_DSSPOOLER_KEY,
6304                                           SPOOL_REG_LOCATION,
6305                                           REG_SZ,
6306                                           buffer.data,
6307                                           buffer.length);
6308
6309                 if (!force_update) {
6310                         notify_printer_location(server_event_context(),
6311                                                 msg_ctx, snum,
6312                                                 printer->location ?
6313                                                 printer->location : "");
6314                 }
6315         }
6316
6317         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6318                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6319                 winreg_set_printer_dataex(mem_ctx,
6320                                           session_info,
6321                                           msg_ctx,
6322                                           printer->sharename,
6323                                           SPOOL_DSSPOOLER_KEY,
6324                                           SPOOL_REG_PRINTSEPARATORFILE,
6325                                           REG_SZ,
6326                                           buffer.data,
6327                                           buffer.length);
6328
6329                 if (!force_update) {
6330                         notify_printer_sepfile(server_event_context(),
6331                                                msg_ctx, snum,
6332                                                printer->sepfile ?
6333                                                printer->sepfile : "");
6334                 }
6335         }
6336
6337         if (force_update || printer->starttime != old_printer->starttime) {
6338                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6339                 SIVAL(buffer.data, 0, printer->starttime);
6340                 winreg_set_printer_dataex(mem_ctx,
6341                                           session_info,
6342                                           msg_ctx,
6343                                           printer->sharename,
6344                                           SPOOL_DSSPOOLER_KEY,
6345                                           SPOOL_REG_PRINTSTARTTIME,
6346                                           REG_DWORD,
6347                                           buffer.data,
6348                                           buffer.length);
6349         }
6350
6351         if (force_update || printer->untiltime != old_printer->untiltime) {
6352                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6353                 SIVAL(buffer.data, 0, printer->untiltime);
6354                 winreg_set_printer_dataex(mem_ctx,
6355                                           session_info,
6356                                           msg_ctx,
6357                                           printer->sharename,
6358                                           SPOOL_DSSPOOLER_KEY,
6359                                           SPOOL_REG_PRINTENDTIME,
6360                                           REG_DWORD,
6361                                           buffer.data,
6362                                           buffer.length);
6363         }
6364
6365         if (force_update || printer->priority != old_printer->priority) {
6366                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6367                 SIVAL(buffer.data, 0, printer->priority);
6368                 winreg_set_printer_dataex(mem_ctx,
6369                                           session_info,
6370                                           msg_ctx,
6371                                           printer->sharename,
6372                                           SPOOL_DSSPOOLER_KEY,
6373                                           SPOOL_REG_PRIORITY,
6374                                           REG_DWORD,
6375                                           buffer.data,
6376                                           buffer.length);
6377         }
6378
6379         if (force_update || printer->attributes != old_printer->attributes) {
6380                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6381                 SIVAL(buffer.data, 0, (printer->attributes &
6382                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6383                 winreg_set_printer_dataex(mem_ctx,
6384                                           session_info,
6385                                           msg_ctx,
6386                                           printer->sharename,
6387                                           SPOOL_DSSPOOLER_KEY,
6388                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6389                                           REG_DWORD,
6390                                           buffer.data,
6391                                           buffer.length);
6392
6393                 switch (printer->attributes & 0x3) {
6394                         case 0:
6395                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6396                                 break;
6397                         case 1:
6398                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6399                                 break;
6400                         case 2:
6401                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6402                                 break;
6403                         default:
6404                                 spooling = "unknown";
6405                 }
6406                 push_reg_sz(mem_ctx, &buffer, spooling);
6407                 winreg_set_printer_dataex(mem_ctx,
6408                                           session_info,
6409                                           msg_ctx,
6410                                           printer->sharename,
6411                                           SPOOL_DSSPOOLER_KEY,
6412                                           SPOOL_REG_PRINTSPOOLING,
6413                                           REG_SZ,
6414                                           buffer.data,
6415                                           buffer.length);
6416         }
6417
6418         push_reg_sz(mem_ctx, &buffer, global_myname());
6419         winreg_set_printer_dataex(mem_ctx,
6420                                   session_info,
6421                                   msg_ctx,
6422                                   printer->sharename,
6423                                   SPOOL_DSSPOOLER_KEY,
6424                                   SPOOL_REG_SHORTSERVERNAME,
6425                                   REG_SZ,
6426                                   buffer.data,
6427                                   buffer.length);
6428
6429         dnsdomname = get_mydnsfullname();
6430         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6431                 longname = talloc_strdup(mem_ctx, dnsdomname);
6432         } else {
6433                 longname = talloc_strdup(mem_ctx, global_myname());
6434         }
6435         if (longname == NULL) {
6436                 result = WERR_NOMEM;
6437                 goto done;
6438         }
6439
6440         push_reg_sz(mem_ctx, &buffer, longname);
6441         winreg_set_printer_dataex(mem_ctx,
6442                                   session_info,
6443                                   msg_ctx,
6444                                   printer->sharename,
6445                                   SPOOL_DSSPOOLER_KEY,
6446                                   SPOOL_REG_SERVERNAME,
6447                                   REG_SZ,
6448                                   buffer.data,
6449                                   buffer.length);
6450
6451         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6452                                   global_myname(), printer->sharename);
6453         push_reg_sz(mem_ctx, &buffer, uncname);
6454         winreg_set_printer_dataex(mem_ctx,
6455                                   session_info,
6456                                   msg_ctx,
6457                                   printer->sharename,
6458                                   SPOOL_DSSPOOLER_KEY,
6459                                   SPOOL_REG_UNCNAME,
6460                                   REG_SZ,
6461                                   buffer.data,
6462                                   buffer.length);
6463
6464 done:
6465         return result;
6466 }
6467
6468 /********************************************************************
6469  * Called by spoolss_api_setprinter
6470  * when updating a printer description.
6471  ********************************************************************/
6472
6473 static WERROR update_printer(struct pipes_struct *p,
6474                              struct policy_handle *handle,
6475                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6476                              struct spoolss_DeviceMode *devmode)
6477 {
6478         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6479         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6480         struct spoolss_PrinterInfo2 *old_printer;
6481         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6482         int snum;
6483         WERROR result = WERR_OK;
6484         TALLOC_CTX *tmp_ctx;
6485
6486         DEBUG(8,("update_printer\n"));
6487
6488         tmp_ctx = talloc_new(p->mem_ctx);
6489         if (tmp_ctx == NULL) {
6490                 return WERR_NOMEM;
6491         }
6492
6493         if (!Printer) {
6494                 result = WERR_BADFID;
6495                 goto done;
6496         }
6497
6498         if (!get_printer_snum(p, handle, &snum, NULL)) {
6499                 result = WERR_BADFID;
6500                 goto done;
6501         }
6502
6503         result = winreg_get_printer(tmp_ctx,
6504                                     get_session_info_system(),
6505                                     p->msg_ctx,
6506                                     lp_const_servicename(snum),
6507                                     &old_printer);
6508         if (!W_ERROR_IS_OK(result)) {
6509                 result = WERR_BADFID;
6510                 goto done;
6511         }
6512
6513         /* Do sanity check on the requested changes for Samba */
6514         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6515                 result = WERR_INVALID_PARAM;
6516                 goto done;
6517         }
6518
6519         /* FIXME!!! If the driver has changed we really should verify that
6520            it is installed before doing much else   --jerry */
6521
6522         /* Check calling user has permission to update printer description */
6523         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6524                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6525                 result = WERR_ACCESS_DENIED;
6526                 goto done;
6527         }
6528
6529         /* Call addprinter hook */
6530         /* Check changes to see if this is really needed */
6531
6532         if (*lp_addprinter_cmd() &&
6533                         (!strequal(printer->drivername, old_printer->drivername) ||
6534                          !strequal(printer->comment, old_printer->comment) ||
6535                          !strequal(printer->portname, old_printer->portname) ||
6536                          !strequal(printer->location, old_printer->location)) )
6537         {
6538                 /* add_printer_hook() will call reload_services() */
6539                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6540                                       printer, p->client_id->addr,
6541                                       p->msg_ctx)) {
6542                         result = WERR_ACCESS_DENIED;
6543                         goto done;
6544                 }
6545         }
6546
6547         update_dsspooler(tmp_ctx,
6548                          get_session_info_system(),
6549                          p->msg_ctx,
6550                          snum,
6551                          printer,
6552                          old_printer);
6553
6554         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6555
6556         if (devmode == NULL) {
6557                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6558         }
6559         result = winreg_update_printer(tmp_ctx,
6560                                        get_session_info_system(),
6561                                        p->msg_ctx,
6562                                        printer->sharename,
6563                                        printer_mask,
6564                                        printer,
6565                                        devmode,
6566                                        NULL);
6567
6568 done:
6569         talloc_free(tmp_ctx);
6570
6571         return result;
6572 }
6573
6574 /****************************************************************************
6575 ****************************************************************************/
6576 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6577                                            struct policy_handle *handle,
6578                                            struct spoolss_SetPrinterInfo7 *info7)
6579 {
6580 #ifdef HAVE_ADS
6581         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6582         WERROR result;
6583         int snum;
6584         struct printer_handle *Printer;
6585
6586         if ( lp_security() != SEC_ADS ) {
6587                 return WERR_UNKNOWN_LEVEL;
6588         }
6589
6590         Printer = find_printer_index_by_hnd(p, handle);
6591
6592         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6593
6594         if (!Printer)
6595                 return WERR_BADFID;
6596
6597         if (!get_printer_snum(p, handle, &snum, NULL))
6598                 return WERR_BADFID;
6599
6600         result = winreg_get_printer(p->mem_ctx,
6601                                     get_session_info_system(),
6602                                     p->msg_ctx,
6603                                     lp_servicename(snum),
6604                                     &pinfo2);
6605         if (!W_ERROR_IS_OK(result)) {
6606                 return WERR_BADFID;
6607         }
6608
6609         nt_printer_publish(pinfo2,
6610                            get_session_info_system(),
6611                            p->msg_ctx,
6612                            pinfo2,
6613                            info7->action);
6614
6615         TALLOC_FREE(pinfo2);
6616         return WERR_OK;
6617 #else
6618         return WERR_UNKNOWN_LEVEL;
6619 #endif
6620 }
6621
6622 /********************************************************************
6623  ********************************************************************/
6624
6625 static WERROR update_printer_devmode(struct pipes_struct *p,
6626                                      struct policy_handle *handle,
6627                                      struct spoolss_DeviceMode *devmode)
6628 {
6629         int snum;
6630         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6631         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6632
6633         DEBUG(8,("update_printer_devmode\n"));
6634
6635         if (!Printer) {
6636                 return WERR_BADFID;
6637         }
6638
6639         if (!get_printer_snum(p, handle, &snum, NULL)) {
6640                 return WERR_BADFID;
6641         }
6642
6643         /* Check calling user has permission to update printer description */
6644         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6645                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6646                 return WERR_ACCESS_DENIED;
6647         }
6648
6649         return winreg_update_printer(p->mem_ctx,
6650                                      get_session_info_system(),
6651                                      p->msg_ctx,
6652                                      lp_const_servicename(snum),
6653                                      info2_mask,
6654                                      NULL,
6655                                      devmode,
6656                                      NULL);
6657 }
6658
6659
6660 /****************************************************************
6661  _spoolss_SetPrinter
6662 ****************************************************************/
6663
6664 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6665                            struct spoolss_SetPrinter *r)
6666 {
6667         WERROR result;
6668
6669         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6670
6671         if (!Printer) {
6672                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6673                         OUR_HANDLE(r->in.handle)));
6674                 return WERR_BADFID;
6675         }
6676
6677         /* check the level */
6678         switch (r->in.info_ctr->level) {
6679                 case 0:
6680                         return control_printer(r->in.handle, r->in.command, p);
6681                 case 2:
6682                         result = update_printer(p, r->in.handle,
6683                                                 r->in.info_ctr,
6684                                                 r->in.devmode_ctr->devmode);
6685                         if (!W_ERROR_IS_OK(result))
6686                                 return result;
6687                         if (r->in.secdesc_ctr->sd)
6688                                 result = update_printer_sec(r->in.handle, p,
6689                                                             r->in.secdesc_ctr);
6690                         return result;
6691                 case 3:
6692                         return update_printer_sec(r->in.handle, p,
6693                                                   r->in.secdesc_ctr);
6694                 case 7:
6695                         return publish_or_unpublish_printer(p, r->in.handle,
6696                                                             r->in.info_ctr->info.info7);
6697                 case 8:
6698                         return update_printer_devmode(p, r->in.handle,
6699                                                       r->in.devmode_ctr->devmode);
6700                 default:
6701                         return WERR_UNKNOWN_LEVEL;
6702         }
6703 }
6704
6705 /****************************************************************
6706  _spoolss_FindClosePrinterNotify
6707 ****************************************************************/
6708
6709 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6710                                        struct spoolss_FindClosePrinterNotify *r)
6711 {
6712         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6713
6714         if (!Printer) {
6715                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6716                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6717                 return WERR_BADFID;
6718         }
6719
6720         if (Printer->notify.cli_chan != NULL &&
6721             Printer->notify.cli_chan->active_connections > 0) {
6722                 int snum = -1;
6723
6724                 if (Printer->printer_type == SPLHND_PRINTER) {
6725                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6726                                 return WERR_BADFID;
6727                         }
6728                 }
6729
6730                 srv_spoolss_replycloseprinter(snum, Printer);
6731         }
6732
6733         Printer->notify.flags=0;
6734         Printer->notify.options=0;
6735         Printer->notify.localmachine[0]='\0';
6736         Printer->notify.printerlocal=0;
6737         TALLOC_FREE(Printer->notify.option);
6738
6739         return WERR_OK;
6740 }
6741
6742 /****************************************************************
6743  _spoolss_AddJob
6744 ****************************************************************/
6745
6746 WERROR _spoolss_AddJob(struct pipes_struct *p,
6747                        struct spoolss_AddJob *r)
6748 {
6749         if (!r->in.buffer && (r->in.offered != 0)) {
6750                 return WERR_INVALID_PARAM;
6751         }
6752
6753         /* this is what a NT server returns for AddJob. AddJob must fail on
6754          * non-local printers */
6755
6756         if (r->in.level != 1) {
6757                 return WERR_UNKNOWN_LEVEL;
6758         }
6759
6760         return WERR_INVALID_PARAM;
6761 }
6762
6763 /****************************************************************************
6764 fill_job_info1
6765 ****************************************************************************/
6766
6767 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6768                              struct spoolss_JobInfo1 *r,
6769                              const print_queue_struct *queue,
6770                              int position, int snum,
6771                              struct spoolss_PrinterInfo2 *pinfo2)
6772 {
6773         struct tm *t;
6774
6775         t = gmtime(&queue->time);
6776
6777         r->job_id               = queue->job;
6778
6779         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6780         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6781         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6782         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6783         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6784         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6785         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6786         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6787         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6788         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6789         r->text_status          = talloc_strdup(mem_ctx, "");
6790         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6791
6792         r->status               = nt_printj_status(queue->status);
6793         r->priority             = queue->priority;
6794         r->position             = position;
6795         r->total_pages          = queue->page_count;
6796         r->pages_printed        = 0; /* ??? */
6797
6798         init_systemtime(&r->submitted, t);
6799
6800         return WERR_OK;
6801 }
6802
6803 /****************************************************************************
6804 fill_job_info2
6805 ****************************************************************************/
6806
6807 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6808                              struct spoolss_JobInfo2 *r,
6809                              const print_queue_struct *queue,
6810                              int position, int snum,
6811                              struct spoolss_PrinterInfo2 *pinfo2,
6812                              struct spoolss_DeviceMode *devmode)
6813 {
6814         struct tm *t;
6815
6816         t = gmtime(&queue->time);
6817
6818         r->job_id               = queue->job;
6819
6820         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6821         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6822         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6823         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6824         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6825         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6826         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6827         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6828         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6829         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6830         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6831         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6832         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6833         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6834         r->parameters           = talloc_strdup(mem_ctx, "");
6835         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6836         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6837         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6838
6839         r->devmode              = devmode;
6840
6841         r->text_status          = talloc_strdup(mem_ctx, "");
6842         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6843
6844         r->secdesc              = NULL;
6845
6846         r->status               = nt_printj_status(queue->status);
6847         r->priority             = queue->priority;
6848         r->position             = position;
6849         r->start_time           = 0;
6850         r->until_time           = 0;
6851         r->total_pages          = queue->page_count;
6852         r->size                 = queue->size;
6853         init_systemtime(&r->submitted, t);
6854         r->time                 = 0;
6855         r->pages_printed        = 0; /* ??? */
6856
6857         return WERR_OK;
6858 }
6859
6860 /****************************************************************************
6861 fill_job_info3
6862 ****************************************************************************/
6863
6864 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6865                              struct spoolss_JobInfo3 *r,
6866                              const print_queue_struct *queue,
6867                              const print_queue_struct *next_queue,
6868                              int position, int snum,
6869                              struct spoolss_PrinterInfo2 *pinfo2)
6870 {
6871         r->job_id               = queue->job;
6872         r->next_job_id          = 0;
6873         if (next_queue) {
6874                 r->next_job_id  = next_queue->job;
6875         }
6876         r->reserved             = 0;
6877
6878         return WERR_OK;
6879 }
6880
6881 /****************************************************************************
6882  Enumjobs at level 1.
6883 ****************************************************************************/
6884
6885 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6886                               const print_queue_struct *queue,
6887                               uint32_t num_queues, int snum,
6888                               struct spoolss_PrinterInfo2 *pinfo2,
6889                               union spoolss_JobInfo **info_p,
6890                               uint32_t *count)
6891 {
6892         union spoolss_JobInfo *info;
6893         int i;
6894         WERROR result = WERR_OK;
6895
6896         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6897         W_ERROR_HAVE_NO_MEMORY(info);
6898
6899         *count = num_queues;
6900
6901         for (i=0; i<*count; i++) {
6902                 result = fill_job_info1(info,
6903                                         &info[i].info1,
6904                                         &queue[i],
6905                                         i,
6906                                         snum,
6907                                         pinfo2);
6908                 if (!W_ERROR_IS_OK(result)) {
6909                         goto out;
6910                 }
6911         }
6912
6913  out:
6914         if (!W_ERROR_IS_OK(result)) {
6915                 TALLOC_FREE(info);
6916                 *count = 0;
6917                 return result;
6918         }
6919
6920         *info_p = info;
6921
6922         return WERR_OK;
6923 }
6924
6925 /****************************************************************************
6926  Enumjobs at level 2.
6927 ****************************************************************************/
6928
6929 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6930                               const print_queue_struct *queue,
6931                               uint32_t num_queues, int snum,
6932                               struct spoolss_PrinterInfo2 *pinfo2,
6933                               union spoolss_JobInfo **info_p,
6934                               uint32_t *count)
6935 {
6936         union spoolss_JobInfo *info;
6937         int i;
6938         WERROR result = WERR_OK;
6939
6940         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6941         W_ERROR_HAVE_NO_MEMORY(info);
6942
6943         *count = num_queues;
6944
6945         for (i=0; i<*count; i++) {
6946                 struct spoolss_DeviceMode *devmode;
6947
6948                 result = spoolss_create_default_devmode(info,
6949                                                         pinfo2->printername,
6950                                                         &devmode);
6951                 if (!W_ERROR_IS_OK(result)) {
6952                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6953                         goto out;
6954                 }
6955
6956                 result = fill_job_info2(info,
6957                                         &info[i].info2,
6958                                         &queue[i],
6959                                         i,
6960                                         snum,
6961                                         pinfo2,
6962                                         devmode);
6963                 if (!W_ERROR_IS_OK(result)) {
6964                         goto out;
6965                 }
6966         }
6967
6968  out:
6969         if (!W_ERROR_IS_OK(result)) {
6970                 TALLOC_FREE(info);
6971                 *count = 0;
6972                 return result;
6973         }
6974
6975         *info_p = info;
6976
6977         return WERR_OK;
6978 }
6979
6980 /****************************************************************************
6981  Enumjobs at level 3.
6982 ****************************************************************************/
6983
6984 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6985                               const print_queue_struct *queue,
6986                               uint32_t num_queues, int snum,
6987                               struct spoolss_PrinterInfo2 *pinfo2,
6988                               union spoolss_JobInfo **info_p,
6989                               uint32_t *count)
6990 {
6991         union spoolss_JobInfo *info;
6992         int i;
6993         WERROR result = WERR_OK;
6994
6995         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6996         W_ERROR_HAVE_NO_MEMORY(info);
6997
6998         *count = num_queues;
6999
7000         for (i=0; i<*count; i++) {
7001                 const print_queue_struct *next_queue = NULL;
7002
7003                 if (i+1 < *count) {
7004                         next_queue = &queue[i+1];
7005                 }
7006
7007                 result = fill_job_info3(info,
7008                                         &info[i].info3,
7009                                         &queue[i],
7010                                         next_queue,
7011                                         i,
7012                                         snum,
7013                                         pinfo2);
7014                 if (!W_ERROR_IS_OK(result)) {
7015                         goto out;
7016                 }
7017         }
7018
7019  out:
7020         if (!W_ERROR_IS_OK(result)) {
7021                 TALLOC_FREE(info);
7022                 *count = 0;
7023                 return result;
7024         }
7025
7026         *info_p = info;
7027
7028         return WERR_OK;
7029 }
7030
7031 /****************************************************************
7032  _spoolss_EnumJobs
7033 ****************************************************************/
7034
7035 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7036                          struct spoolss_EnumJobs *r)
7037 {
7038         WERROR result;
7039         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7040         int snum;
7041         print_status_struct prt_status;
7042         print_queue_struct *queue = NULL;
7043         uint32_t count;
7044
7045         /* that's an [in out] buffer */
7046
7047         if (!r->in.buffer && (r->in.offered != 0)) {
7048                 return WERR_INVALID_PARAM;
7049         }
7050
7051         DEBUG(4,("_spoolss_EnumJobs\n"));
7052
7053         *r->out.needed = 0;
7054         *r->out.count = 0;
7055         *r->out.info = NULL;
7056
7057         /* lookup the printer snum and tdb entry */
7058
7059         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7060                 return WERR_BADFID;
7061         }
7062
7063         result = winreg_get_printer(p->mem_ctx,
7064                                     get_session_info_system(),
7065                                     p->msg_ctx,
7066                                     lp_const_servicename(snum),
7067                                     &pinfo2);
7068         if (!W_ERROR_IS_OK(result)) {
7069                 return result;
7070         }
7071
7072         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7073         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7074                 count, prt_status.status, prt_status.message));
7075
7076         if (count == 0) {
7077                 SAFE_FREE(queue);
7078                 TALLOC_FREE(pinfo2);
7079                 return WERR_OK;
7080         }
7081
7082         switch (r->in.level) {
7083         case 1:
7084                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7085                                          pinfo2, r->out.info, r->out.count);
7086                 break;
7087         case 2:
7088                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7089                                          pinfo2, r->out.info, r->out.count);
7090                 break;
7091         case 3:
7092                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7093                                          pinfo2, r->out.info, r->out.count);
7094                 break;
7095         default:
7096                 result = WERR_UNKNOWN_LEVEL;
7097                 break;
7098         }
7099
7100         SAFE_FREE(queue);
7101         TALLOC_FREE(pinfo2);
7102
7103         if (!W_ERROR_IS_OK(result)) {
7104                 return result;
7105         }
7106
7107         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7108                                                      spoolss_EnumJobs,
7109                                                      *r->out.info, r->in.level,
7110                                                      *r->out.count);
7111         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7112         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7113
7114         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7115 }
7116
7117 /****************************************************************
7118  _spoolss_ScheduleJob
7119 ****************************************************************/
7120
7121 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7122                             struct spoolss_ScheduleJob *r)
7123 {
7124         return WERR_OK;
7125 }
7126
7127 /****************************************************************
7128 ****************************************************************/
7129
7130 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7131                                struct messaging_context *msg_ctx,
7132                                const char *printer_name,
7133                                uint32_t job_id,
7134                                struct spoolss_SetJobInfo1 *r)
7135 {
7136         char *old_doc_name;
7137
7138         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7139                 return WERR_BADFID;
7140         }
7141
7142         if (strequal(old_doc_name, r->document_name)) {
7143                 return WERR_OK;
7144         }
7145
7146         if (!print_job_set_name(server_event_context(), msg_ctx,
7147                                 printer_name, job_id, r->document_name)) {
7148                 return WERR_BADFID;
7149         }
7150
7151         return WERR_OK;
7152 }
7153
7154 /****************************************************************
7155  _spoolss_SetJob
7156 ****************************************************************/
7157
7158 WERROR _spoolss_SetJob(struct pipes_struct *p,
7159                        struct spoolss_SetJob *r)
7160 {
7161         const struct auth_serversupplied_info *session_info = p->session_info;
7162         int snum;
7163         WERROR errcode = WERR_BADFUNC;
7164
7165         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7166                 return WERR_BADFID;
7167         }
7168
7169         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7170                 return WERR_INVALID_PRINTER_NAME;
7171         }
7172
7173         switch (r->in.command) {
7174         case SPOOLSS_JOB_CONTROL_CANCEL:
7175         case SPOOLSS_JOB_CONTROL_DELETE:
7176                 errcode = print_job_delete(session_info, p->msg_ctx,
7177                                            snum, r->in.job_id);
7178                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7179                         errcode = WERR_OK;
7180                 }
7181                 break;
7182         case SPOOLSS_JOB_CONTROL_PAUSE:
7183                 if (print_job_pause(session_info, p->msg_ctx,
7184                                     snum, r->in.job_id, &errcode)) {
7185                         errcode = WERR_OK;
7186                 }
7187                 break;
7188         case SPOOLSS_JOB_CONTROL_RESTART:
7189         case SPOOLSS_JOB_CONTROL_RESUME:
7190                 if (print_job_resume(session_info, p->msg_ctx,
7191                                      snum, r->in.job_id, &errcode)) {
7192                         errcode = WERR_OK;
7193                 }
7194                 break;
7195         case 0:
7196                 errcode = WERR_OK;
7197                 break;
7198         default:
7199                 return WERR_UNKNOWN_LEVEL;
7200         }
7201
7202         if (!W_ERROR_IS_OK(errcode)) {
7203                 return errcode;
7204         }
7205
7206         if (r->in.ctr == NULL) {
7207                 return errcode;
7208         }
7209
7210         switch (r->in.ctr->level) {
7211         case 1:
7212                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7213                                            lp_const_servicename(snum),
7214                                            r->in.job_id,
7215                                            r->in.ctr->info.info1);
7216                 break;
7217         case 2:
7218         case 3:
7219         case 4:
7220         default:
7221                 return WERR_UNKNOWN_LEVEL;
7222         }
7223
7224         return errcode;
7225 }
7226
7227 /****************************************************************************
7228  Enumerates all printer drivers by level and architecture.
7229 ****************************************************************************/
7230
7231 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7232                                                        const struct auth_serversupplied_info *session_info,
7233                                                        struct messaging_context *msg_ctx,
7234                                                        const char *servername,
7235                                                        const char *architecture,
7236                                                        uint32_t level,
7237                                                        union spoolss_DriverInfo **info_p,
7238                                                        uint32_t *count_p)
7239 {
7240         int i;
7241         uint32_t version;
7242         struct spoolss_DriverInfo8 *driver;
7243         union spoolss_DriverInfo *info = NULL;
7244         uint32_t count = 0;
7245         WERROR result = WERR_OK;
7246         uint32_t num_drivers;
7247         const char **drivers;
7248
7249         *count_p = 0;
7250         *info_p = NULL;
7251
7252         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7253                 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7254                                                 architecture, version,
7255                                                 &num_drivers, &drivers);
7256                 if (!W_ERROR_IS_OK(result)) {
7257                         goto out;
7258                 }
7259                 DEBUG(4, ("we have:[%d] drivers in environment"
7260                           " [%s] and version [%d]\n",
7261                           num_drivers, architecture, version));
7262
7263                 if (num_drivers != 0) {
7264                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7265                                                     union spoolss_DriverInfo,
7266                                                     count + num_drivers);
7267                         if (!info) {
7268                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7269                                         "failed to enlarge driver info buffer!\n"));
7270                                 result = WERR_NOMEM;
7271                                 goto out;
7272                         }
7273                 }
7274
7275                 for (i = 0; i < num_drivers; i++) {
7276                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7277
7278                         result = winreg_get_driver(mem_ctx, session_info,
7279                                                    msg_ctx,
7280                                                    architecture, drivers[i],
7281                                                    version, &driver);
7282                         if (!W_ERROR_IS_OK(result)) {
7283                                 goto out;
7284                         }
7285
7286                         switch (level) {
7287                         case 1:
7288                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7289                                                                    driver, servername);
7290                                 break;
7291                         case 2:
7292                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7293                                                                    driver, servername);
7294                                 break;
7295                         case 3:
7296                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7297                                                                    driver, servername);
7298                                 break;
7299                         case 4:
7300                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7301                                                                    driver, servername);
7302                                 break;
7303                         case 5:
7304                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7305                                                                    driver, servername);
7306                                 break;
7307                         case 6:
7308                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7309                                                                    driver, servername);
7310                                 break;
7311                         case 8:
7312                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7313                                                                    driver, servername);
7314                                 break;
7315                         default:
7316                                 result = WERR_UNKNOWN_LEVEL;
7317                                 break;
7318                         }
7319
7320                         TALLOC_FREE(driver);
7321
7322                         if (!W_ERROR_IS_OK(result)) {
7323                                 goto out;
7324                         }
7325                 }
7326
7327                 count += num_drivers;
7328                 TALLOC_FREE(drivers);
7329         }
7330
7331  out:
7332         TALLOC_FREE(drivers);
7333
7334         if (!W_ERROR_IS_OK(result)) {
7335                 TALLOC_FREE(info);
7336                 return result;
7337         }
7338
7339         *info_p = info;
7340         *count_p = count;
7341
7342         return WERR_OK;
7343 }
7344
7345 /****************************************************************************
7346  Enumerates all printer drivers by level.
7347 ****************************************************************************/
7348
7349 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7350                                        const struct auth_serversupplied_info *session_info,
7351                                        struct messaging_context *msg_ctx,
7352                                        const char *servername,
7353                                        const char *architecture,
7354                                        uint32_t level,
7355                                        union spoolss_DriverInfo **info_p,
7356                                        uint32_t *count_p)
7357 {
7358         uint32_t a,i;
7359         WERROR result = WERR_OK;
7360
7361         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7362
7363                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7364
7365                         union spoolss_DriverInfo *info = NULL;
7366                         uint32_t count = 0;
7367
7368                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7369                                                                           session_info,
7370                                                                           msg_ctx,
7371                                                                           servername,
7372                                                                           archi_table[a].long_archi,
7373                                                                           level,
7374                                                                           &info,
7375                                                                           &count);
7376                         if (!W_ERROR_IS_OK(result)) {
7377                                 continue;
7378                         }
7379
7380                         for (i=0; i < count; i++) {
7381                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7382                                              info[i], info_p, count_p);
7383                         }
7384                 }
7385
7386                 return result;
7387         }
7388
7389         return enumprinterdrivers_level_by_architecture(mem_ctx,
7390                                                         session_info,
7391                                                         msg_ctx,
7392                                                         servername,
7393                                                         architecture,
7394                                                         level,
7395                                                         info_p,
7396                                                         count_p);
7397 }
7398
7399 /****************************************************************
7400  _spoolss_EnumPrinterDrivers
7401 ****************************************************************/
7402
7403 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7404                                    struct spoolss_EnumPrinterDrivers *r)
7405 {
7406         const char *cservername;
7407         WERROR result;
7408
7409         /* that's an [in out] buffer */
7410
7411         if (!r->in.buffer && (r->in.offered != 0)) {
7412                 return WERR_INVALID_PARAM;
7413         }
7414
7415         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7416
7417         *r->out.needed = 0;
7418         *r->out.count = 0;
7419         *r->out.info = NULL;
7420
7421         cservername = canon_servername(r->in.server);
7422
7423         if (!is_myname_or_ipaddr(cservername)) {
7424                 return WERR_UNKNOWN_PRINTER_DRIVER;
7425         }
7426
7427         result = enumprinterdrivers_level(p->mem_ctx,
7428                                           get_session_info_system(),
7429                                           p->msg_ctx,
7430                                           cservername,
7431                                           r->in.environment,
7432                                           r->in.level,
7433                                           r->out.info,
7434                                           r->out.count);
7435         if (!W_ERROR_IS_OK(result)) {
7436                 return result;
7437         }
7438
7439         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7440                                                      spoolss_EnumPrinterDrivers,
7441                                                      *r->out.info, r->in.level,
7442                                                      *r->out.count);
7443         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7444         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7445
7446         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7447 }
7448
7449 /****************************************************************
7450  _spoolss_EnumForms
7451 ****************************************************************/
7452
7453 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7454                           struct spoolss_EnumForms *r)
7455 {
7456         WERROR result;
7457
7458         *r->out.count = 0;
7459         *r->out.needed = 0;
7460         *r->out.info = NULL;
7461
7462         /* that's an [in out] buffer */
7463
7464         if (!r->in.buffer && (r->in.offered != 0) ) {
7465                 return WERR_INVALID_PARAM;
7466         }
7467
7468         DEBUG(4,("_spoolss_EnumForms\n"));
7469         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7470         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7471
7472         switch (r->in.level) {
7473         case 1:
7474                 result = winreg_printer_enumforms1(p->mem_ctx,
7475                                                    get_session_info_system(),
7476                                                    p->msg_ctx,
7477                                                    r->out.count,
7478                                                    r->out.info);
7479                 break;
7480         default:
7481                 result = WERR_UNKNOWN_LEVEL;
7482                 break;
7483         }
7484
7485         if (!W_ERROR_IS_OK(result)) {
7486                 return result;
7487         }
7488
7489         if (*r->out.count == 0) {
7490                 return WERR_NO_MORE_ITEMS;
7491         }
7492
7493         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7494                                                      spoolss_EnumForms,
7495                                                      *r->out.info, r->in.level,
7496                                                      *r->out.count);
7497         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7498         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7499
7500         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7501 }
7502
7503 /****************************************************************
7504  _spoolss_GetForm
7505 ****************************************************************/
7506
7507 WERROR _spoolss_GetForm(struct pipes_struct *p,
7508                         struct spoolss_GetForm *r)
7509 {
7510         WERROR result;
7511
7512         /* that's an [in out] buffer */
7513
7514         if (!r->in.buffer && (r->in.offered != 0)) {
7515                 return WERR_INVALID_PARAM;
7516         }
7517
7518         DEBUG(4,("_spoolss_GetForm\n"));
7519         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7520         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7521
7522         switch (r->in.level) {
7523         case 1:
7524                 result = winreg_printer_getform1(p->mem_ctx,
7525                                                  get_session_info_system(),
7526                                                  p->msg_ctx,
7527                                                  r->in.form_name,
7528                                                  &r->out.info->info1);
7529                 break;
7530         default:
7531                 result = WERR_UNKNOWN_LEVEL;
7532                 break;
7533         }
7534
7535         if (!W_ERROR_IS_OK(result)) {
7536                 TALLOC_FREE(r->out.info);
7537                 return result;
7538         }
7539
7540         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7541                                                r->out.info, r->in.level);
7542         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7543
7544         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7545 }
7546
7547 /****************************************************************************
7548 ****************************************************************************/
7549
7550 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7551                           struct spoolss_PortInfo1 *r,
7552                           const char *name)
7553 {
7554         r->port_name = talloc_strdup(mem_ctx, name);
7555         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7556
7557         return WERR_OK;
7558 }
7559
7560 /****************************************************************************
7561  TODO: This probably needs distinguish between TCP/IP and Local ports
7562  somehow.
7563 ****************************************************************************/
7564
7565 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7566                           struct spoolss_PortInfo2 *r,
7567                           const char *name)
7568 {
7569         r->port_name = talloc_strdup(mem_ctx, name);
7570         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7571
7572         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7573         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7574
7575         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7576         W_ERROR_HAVE_NO_MEMORY(r->description);
7577
7578         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7579         r->reserved = 0;
7580
7581         return WERR_OK;
7582 }
7583
7584
7585 /****************************************************************************
7586  wrapper around the enumer ports command
7587 ****************************************************************************/
7588
7589 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7590 {
7591         char *cmd = lp_enumports_cmd();
7592         char **qlines = NULL;
7593         char *command = NULL;
7594         int numlines;
7595         int ret;
7596         int fd;
7597
7598         *count = 0;
7599         *lines = NULL;
7600
7601         /* if no hook then just fill in the default port */
7602
7603         if ( !*cmd ) {
7604                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7605                         return WERR_NOMEM;
7606                 }
7607                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7608                         TALLOC_FREE(qlines);
7609                         return WERR_NOMEM;
7610                 }
7611                 qlines[1] = NULL;
7612                 numlines = 1;
7613         }
7614         else {
7615                 /* we have a valid enumport command */
7616
7617                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7618                 if (!command) {
7619                         return WERR_NOMEM;
7620                 }
7621
7622                 DEBUG(10,("Running [%s]\n", command));
7623                 ret = smbrun(command, &fd);
7624                 DEBUG(10,("Returned [%d]\n", ret));
7625                 TALLOC_FREE(command);
7626                 if (ret != 0) {
7627                         if (fd != -1) {
7628                                 close(fd);
7629                         }
7630                         return WERR_ACCESS_DENIED;
7631                 }
7632
7633                 numlines = 0;
7634                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7635                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7636                 close(fd);
7637         }
7638
7639         *count = numlines;
7640         *lines = qlines;
7641
7642         return WERR_OK;
7643 }
7644
7645 /****************************************************************************
7646  enumports level 1.
7647 ****************************************************************************/
7648
7649 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7650                                 union spoolss_PortInfo **info_p,
7651                                 uint32_t *count)
7652 {
7653         union spoolss_PortInfo *info = NULL;
7654         int i=0;
7655         WERROR result = WERR_OK;
7656         char **qlines = NULL;
7657         int numlines = 0;
7658
7659         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7660         if (!W_ERROR_IS_OK(result)) {
7661                 goto out;
7662         }
7663
7664         if (numlines) {
7665                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7666                 if (!info) {
7667                         DEBUG(10,("Returning WERR_NOMEM\n"));
7668                         result = WERR_NOMEM;
7669                         goto out;
7670                 }
7671
7672                 for (i=0; i<numlines; i++) {
7673                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7674                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7675                         if (!W_ERROR_IS_OK(result)) {
7676                                 goto out;
7677                         }
7678                 }
7679         }
7680         TALLOC_FREE(qlines);
7681
7682 out:
7683         if (!W_ERROR_IS_OK(result)) {
7684                 TALLOC_FREE(info);
7685                 TALLOC_FREE(qlines);
7686                 *count = 0;
7687                 *info_p = NULL;
7688                 return result;
7689         }
7690
7691         *info_p = info;
7692         *count = numlines;
7693
7694         return WERR_OK;
7695 }
7696
7697 /****************************************************************************
7698  enumports level 2.
7699 ****************************************************************************/
7700
7701 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7702                                 union spoolss_PortInfo **info_p,
7703                                 uint32_t *count)
7704 {
7705         union spoolss_PortInfo *info = NULL;
7706         int i=0;
7707         WERROR result = WERR_OK;
7708         char **qlines = NULL;
7709         int numlines = 0;
7710
7711         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7712         if (!W_ERROR_IS_OK(result)) {
7713                 goto out;
7714         }
7715
7716         if (numlines) {
7717                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7718                 if (!info) {
7719                         DEBUG(10,("Returning WERR_NOMEM\n"));
7720                         result = WERR_NOMEM;
7721                         goto out;
7722                 }
7723
7724                 for (i=0; i<numlines; i++) {
7725                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7726                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7727                         if (!W_ERROR_IS_OK(result)) {
7728                                 goto out;
7729                         }
7730                 }
7731         }
7732         TALLOC_FREE(qlines);
7733
7734 out:
7735         if (!W_ERROR_IS_OK(result)) {
7736                 TALLOC_FREE(info);
7737                 TALLOC_FREE(qlines);
7738                 *count = 0;
7739                 *info_p = NULL;
7740                 return result;
7741         }
7742
7743         *info_p = info;
7744         *count = numlines;
7745
7746         return WERR_OK;
7747 }
7748
7749 /****************************************************************
7750  _spoolss_EnumPorts
7751 ****************************************************************/
7752
7753 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7754                           struct spoolss_EnumPorts *r)
7755 {
7756         WERROR result;
7757
7758         /* that's an [in out] buffer */
7759
7760         if (!r->in.buffer && (r->in.offered != 0)) {
7761                 return WERR_INVALID_PARAM;
7762         }
7763
7764         DEBUG(4,("_spoolss_EnumPorts\n"));
7765
7766         *r->out.count = 0;
7767         *r->out.needed = 0;
7768         *r->out.info = NULL;
7769
7770         switch (r->in.level) {
7771         case 1:
7772                 result = enumports_level_1(p->mem_ctx, r->out.info,
7773                                            r->out.count);
7774                 break;
7775         case 2:
7776                 result = enumports_level_2(p->mem_ctx, r->out.info,
7777                                            r->out.count);
7778                 break;
7779         default:
7780                 return WERR_UNKNOWN_LEVEL;
7781         }
7782
7783         if (!W_ERROR_IS_OK(result)) {
7784                 return result;
7785         }
7786
7787         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7788                                                      spoolss_EnumPorts,
7789                                                      *r->out.info, r->in.level,
7790                                                      *r->out.count);
7791         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7792         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7793
7794         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7795 }
7796
7797 /****************************************************************************
7798 ****************************************************************************/
7799
7800 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7801                                            const char *server,
7802                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7803                                            struct spoolss_DeviceMode *devmode,
7804                                            struct security_descriptor *secdesc,
7805                                            struct spoolss_UserLevelCtr *user_ctr,
7806                                            struct policy_handle *handle)
7807 {
7808         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7809         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7810         int     snum;
7811         WERROR err = WERR_OK;
7812
7813         /* samba does not have a concept of local, non-shared printers yet, so
7814          * make sure we always setup sharename - gd */
7815         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7816             (info2->printername != NULL && info2->printername[0] != '\0')) {
7817                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7818                         "no sharename has been set, setting printername %s as sharename\n",
7819                         info2->printername));
7820                 info2->sharename = info2->printername;
7821         }
7822
7823         /* check to see if the printer already exists */
7824         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7825                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7826                         info2->sharename));
7827                 return WERR_PRINTER_ALREADY_EXISTS;
7828         }
7829
7830         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7831                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7832                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7833                                 info2->printername));
7834                         return WERR_PRINTER_ALREADY_EXISTS;
7835                 }
7836         }
7837
7838         /* validate printer info struct */
7839         if (!info2->printername || strlen(info2->printername) == 0) {
7840                 return WERR_INVALID_PRINTER_NAME;
7841         }
7842         if (!info2->portname || strlen(info2->portname) == 0) {
7843                 return WERR_UNKNOWN_PORT;
7844         }
7845         if (!info2->drivername || strlen(info2->drivername) == 0) {
7846                 return WERR_UNKNOWN_PRINTER_DRIVER;
7847         }
7848         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7849                 return WERR_UNKNOWN_PRINTPROCESSOR;
7850         }
7851
7852         /* FIXME!!!  smbd should check to see if the driver is installed before
7853            trying to add a printer like this  --jerry */
7854
7855         if (*lp_addprinter_cmd() ) {
7856                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7857                                        info2, p->client_id->addr,
7858                                        p->msg_ctx) ) {
7859                         return WERR_ACCESS_DENIED;
7860                 }
7861         } else {
7862                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7863                         "smb.conf parameter \"addprinter command\" is defined. This "
7864                         "parameter must exist for this call to succeed\n",
7865                         info2->sharename ));
7866         }
7867
7868         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7869                 return WERR_ACCESS_DENIED;
7870         }
7871
7872         /* you must be a printer admin to add a new printer */
7873         if (!print_access_check(p->session_info,
7874                                 p->msg_ctx,
7875                                 snum,
7876                                 PRINTER_ACCESS_ADMINISTER)) {
7877                 return WERR_ACCESS_DENIED;
7878         }
7879
7880         /*
7881          * Do sanity check on the requested changes for Samba.
7882          */
7883
7884         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7885                 return WERR_INVALID_PARAM;
7886         }
7887
7888         if (devmode == NULL) {
7889                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7890         }
7891
7892         update_dsspooler(p->mem_ctx,
7893                          get_session_info_system(),
7894                          p->msg_ctx,
7895                          0,
7896                          info2,
7897                          NULL);
7898
7899         err = winreg_update_printer(p->mem_ctx,
7900                                     get_session_info_system(),
7901                                     p->msg_ctx,
7902                                     info2->sharename,
7903                                     info2_mask,
7904                                     info2,
7905                                     devmode,
7906                                     secdesc);
7907         if (!W_ERROR_IS_OK(err)) {
7908                 return err;
7909         }
7910
7911         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7912         if (!W_ERROR_IS_OK(err)) {
7913                 /* Handle open failed - remove addition. */
7914                 ZERO_STRUCTP(handle);
7915                 return err;
7916         }
7917
7918         return WERR_OK;
7919 }
7920
7921 /****************************************************************
7922  _spoolss_AddPrinterEx
7923 ****************************************************************/
7924
7925 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7926                              struct spoolss_AddPrinterEx *r)
7927 {
7928         switch (r->in.info_ctr->level) {
7929         case 1:
7930                 /* we don't handle yet */
7931                 /* but I know what to do ... */
7932                 return WERR_UNKNOWN_LEVEL;
7933         case 2:
7934                 return spoolss_addprinterex_level_2(p, r->in.server,
7935                                                     r->in.info_ctr,
7936                                                     r->in.devmode_ctr->devmode,
7937                                                     r->in.secdesc_ctr->sd,
7938                                                     r->in.userlevel_ctr,
7939                                                     r->out.handle);
7940         default:
7941                 return WERR_UNKNOWN_LEVEL;
7942         }
7943 }
7944
7945 /****************************************************************
7946  _spoolss_AddPrinter
7947 ****************************************************************/
7948
7949 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7950                            struct spoolss_AddPrinter *r)
7951 {
7952         struct spoolss_AddPrinterEx a;
7953         struct spoolss_UserLevelCtr userlevel_ctr;
7954
7955         ZERO_STRUCT(userlevel_ctr);
7956
7957         userlevel_ctr.level = 1;
7958
7959         a.in.server             = r->in.server;
7960         a.in.info_ctr           = r->in.info_ctr;
7961         a.in.devmode_ctr        = r->in.devmode_ctr;
7962         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7963         a.in.userlevel_ctr      = &userlevel_ctr;
7964         a.out.handle            = r->out.handle;
7965
7966         return _spoolss_AddPrinterEx(p, &a);
7967 }
7968
7969 /****************************************************************
7970  _spoolss_AddPrinterDriverEx
7971 ****************************************************************/
7972
7973 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7974                                    struct spoolss_AddPrinterDriverEx *r)
7975 {
7976         WERROR err = WERR_OK;
7977         const char *driver_name = NULL;
7978         uint32_t version;
7979         const char *fn;
7980
7981         switch (p->opnum) {
7982                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7983                         fn = "_spoolss_AddPrinterDriver";
7984                         break;
7985                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7986                         fn = "_spoolss_AddPrinterDriverEx";
7987                         break;
7988                 default:
7989                         return WERR_INVALID_PARAM;
7990         }
7991
7992         /*
7993          * we only support the semantics of AddPrinterDriver()
7994          * i.e. only copy files that are newer than existing ones
7995          */
7996
7997         if (r->in.flags == 0) {
7998                 return WERR_INVALID_PARAM;
7999         }
8000
8001         if (r->in.flags != APD_COPY_NEW_FILES) {
8002                 return WERR_ACCESS_DENIED;
8003         }
8004
8005         /* FIXME */
8006         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8007                 /* Clever hack from Martin Zielinski <mz@seh.de>
8008                  * to allow downgrade from level 8 (Vista).
8009                  */
8010                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8011                         r->in.info_ctr->level));
8012                 return WERR_UNKNOWN_LEVEL;
8013         }
8014
8015         DEBUG(5,("Cleaning driver's information\n"));
8016         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8017         if (!W_ERROR_IS_OK(err))
8018                 goto done;
8019
8020         DEBUG(5,("Moving driver to final destination\n"));
8021         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8022         if (!W_ERROR_IS_OK(err)) {
8023                 goto done;
8024         }
8025
8026         err = winreg_add_driver(p->mem_ctx,
8027                                 get_session_info_system(),
8028                                 p->msg_ctx,
8029                                 r->in.info_ctr,
8030                                 &driver_name,
8031                                 &version);
8032         if (!W_ERROR_IS_OK(err)) {
8033                 goto done;
8034         }
8035
8036         /*
8037          * I think this is where he DrvUpgradePrinter() hook would be
8038          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8039          * server.  Right now, we just need to send ourselves a message
8040          * to update each printer bound to this driver.   --jerry
8041          */
8042
8043         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8044                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8045                         fn, driver_name));
8046         }
8047
8048 done:
8049         return err;
8050 }
8051
8052 /****************************************************************
8053  _spoolss_AddPrinterDriver
8054 ****************************************************************/
8055
8056 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8057                                  struct spoolss_AddPrinterDriver *r)
8058 {
8059         struct spoolss_AddPrinterDriverEx a;
8060
8061         switch (r->in.info_ctr->level) {
8062         case 2:
8063         case 3:
8064         case 4:
8065         case 5:
8066                 break;
8067         default:
8068                 return WERR_UNKNOWN_LEVEL;
8069         }
8070
8071         a.in.servername         = r->in.servername;
8072         a.in.info_ctr           = r->in.info_ctr;
8073         a.in.flags              = APD_COPY_NEW_FILES;
8074
8075         return _spoolss_AddPrinterDriverEx(p, &a);
8076 }
8077
8078 /****************************************************************************
8079 ****************************************************************************/
8080
8081 struct _spoolss_paths {
8082         int type;
8083         const char *share;
8084         const char *dir;
8085 };
8086
8087 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8088
8089 static const struct _spoolss_paths spoolss_paths[]= {
8090         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8091         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8092 };
8093
8094 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8095                                           const char *servername,
8096                                           const char *environment,
8097                                           int component,
8098                                           char **path)
8099 {
8100         const char *pservername = NULL;
8101         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8102         const char *short_archi;
8103
8104         *path = NULL;
8105
8106         /* environment may be empty */
8107         if (environment && strlen(environment)) {
8108                 long_archi = environment;
8109         }
8110
8111         /* servername may be empty */
8112         if (servername && strlen(servername)) {
8113                 pservername = canon_servername(servername);
8114
8115                 if (!is_myname_or_ipaddr(pservername)) {
8116                         return WERR_INVALID_PARAM;
8117                 }
8118         }
8119
8120         if (!(short_archi = get_short_archi(long_archi))) {
8121                 return WERR_INVALID_ENVIRONMENT;
8122         }
8123
8124         switch (component) {
8125         case SPOOLSS_PRTPROCS_PATH:
8126         case SPOOLSS_DRIVER_PATH:
8127                 if (pservername) {
8128                         *path = talloc_asprintf(mem_ctx,
8129                                         "\\\\%s\\%s\\%s",
8130                                         pservername,
8131                                         spoolss_paths[component].share,
8132                                         short_archi);
8133                 } else {
8134                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8135                                         SPOOLSS_DEFAULT_SERVER_PATH,
8136                                         spoolss_paths[component].dir,
8137                                         short_archi);
8138                 }
8139                 break;
8140         default:
8141                 return WERR_INVALID_PARAM;
8142         }
8143
8144         if (!*path) {
8145                 return WERR_NOMEM;
8146         }
8147
8148         return WERR_OK;
8149 }
8150
8151 /****************************************************************************
8152 ****************************************************************************/
8153
8154 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8155                                           const char *servername,
8156                                           const char *environment,
8157                                           struct spoolss_DriverDirectoryInfo1 *r)
8158 {
8159         WERROR werr;
8160         char *path = NULL;
8161
8162         werr = compose_spoolss_server_path(mem_ctx,
8163                                            servername,
8164                                            environment,
8165                                            SPOOLSS_DRIVER_PATH,
8166                                            &path);
8167         if (!W_ERROR_IS_OK(werr)) {
8168                 return werr;
8169         }
8170
8171         DEBUG(4,("printer driver directory: [%s]\n", path));
8172
8173         r->directory_name = path;
8174
8175         return WERR_OK;
8176 }
8177
8178 /****************************************************************
8179  _spoolss_GetPrinterDriverDirectory
8180 ****************************************************************/
8181
8182 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8183                                           struct spoolss_GetPrinterDriverDirectory *r)
8184 {
8185         WERROR werror;
8186
8187         /* that's an [in out] buffer */
8188
8189         if (!r->in.buffer && (r->in.offered != 0)) {
8190                 return WERR_INVALID_PARAM;
8191         }
8192
8193         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8194                 r->in.level));
8195
8196         *r->out.needed = 0;
8197
8198         /* r->in.level is ignored */
8199
8200         werror = getprinterdriverdir_level_1(p->mem_ctx,
8201                                              r->in.server,
8202                                              r->in.environment,
8203                                              &r->out.info->info1);
8204         if (!W_ERROR_IS_OK(werror)) {
8205                 TALLOC_FREE(r->out.info);
8206                 return werror;
8207         }
8208
8209         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8210                                                r->out.info, r->in.level);
8211         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8212
8213         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8214 }
8215
8216 /****************************************************************
8217  _spoolss_EnumPrinterData
8218 ****************************************************************/
8219
8220 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8221                                 struct spoolss_EnumPrinterData *r)
8222 {
8223         WERROR result;
8224         struct spoolss_EnumPrinterDataEx r2;
8225         uint32_t count;
8226         struct spoolss_PrinterEnumValues *info, *val = NULL;
8227         uint32_t needed;
8228
8229         r2.in.handle    = r->in.handle;
8230         r2.in.key_name  = "PrinterDriverData";
8231         r2.in.offered   = 0;
8232         r2.out.count    = &count;
8233         r2.out.info     = &info;
8234         r2.out.needed   = &needed;
8235
8236         result = _spoolss_EnumPrinterDataEx(p, &r2);
8237         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8238                 r2.in.offered = needed;
8239                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8240         }
8241         if (!W_ERROR_IS_OK(result)) {
8242                 return result;
8243         }
8244
8245         /*
8246          * The NT machine wants to know the biggest size of value and data
8247          *
8248          * cf: MSDN EnumPrinterData remark section
8249          */
8250
8251         if (!r->in.value_offered && !r->in.data_offered) {
8252                 uint32_t biggest_valuesize = 0;
8253                 uint32_t biggest_datasize = 0;
8254                 int i, name_length;
8255
8256                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8257
8258                 for (i=0; i<count; i++) {
8259
8260                         name_length = strlen(info[i].value_name);
8261                         if (strlen(info[i].value_name) > biggest_valuesize) {
8262                                 biggest_valuesize = name_length;
8263                         }
8264
8265                         if (info[i].data_length > biggest_datasize) {
8266                                 biggest_datasize = info[i].data_length;
8267                         }
8268
8269                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8270                                 biggest_datasize));
8271                 }
8272
8273                 /* the value is an UNICODE string but real_value_size is the length
8274                    in bytes including the trailing 0 */
8275
8276                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8277                 *r->out.data_needed  = biggest_datasize;
8278
8279                 DEBUG(6,("final values: [%d], [%d]\n",
8280                         *r->out.value_needed, *r->out.data_needed));
8281
8282                 return WERR_OK;
8283         }
8284
8285         if (r->in.enum_index < count) {
8286                 val = &info[r->in.enum_index];
8287         }
8288
8289         if (val == NULL) {
8290                 /* out_value should default to "" or else NT4 has
8291                    problems unmarshalling the response */
8292
8293                 if (r->in.value_offered) {
8294                         *r->out.value_needed = 1;
8295                         r->out.value_name = talloc_strdup(r, "");
8296                         if (!r->out.value_name) {
8297                                 return WERR_NOMEM;
8298                         }
8299                 } else {
8300                         r->out.value_name = NULL;
8301                         *r->out.value_needed = 0;
8302                 }
8303
8304                 /* the data is counted in bytes */
8305
8306                 *r->out.data_needed = r->in.data_offered;
8307
8308                 result = WERR_NO_MORE_ITEMS;
8309         } else {
8310                 /*
8311                  * the value is:
8312                  * - counted in bytes in the request
8313                  * - counted in UNICODE chars in the max reply
8314                  * - counted in bytes in the real size
8315                  *
8316                  * take a pause *before* coding not *during* coding
8317                  */
8318
8319                 /* name */
8320                 if (r->in.value_offered) {
8321                         r->out.value_name = talloc_strdup(r, val->value_name);
8322                         if (!r->out.value_name) {
8323                                 return WERR_NOMEM;
8324                         }
8325                         *r->out.value_needed = val->value_name_len;
8326                 } else {
8327                         r->out.value_name = NULL;
8328                         *r->out.value_needed = 0;
8329                 }
8330
8331                 /* type */
8332
8333                 *r->out.type = val->type;
8334
8335                 /* data - counted in bytes */
8336
8337                 /*
8338                  * See the section "Dynamically Typed Query Parameters"
8339                  * in MS-RPRN.
8340                  */
8341
8342                 if (r->out.data && val->data && val->data->data &&
8343                                 val->data_length && r->in.data_offered) {
8344                         memcpy(r->out.data, val->data->data,
8345                                 MIN(val->data_length,r->in.data_offered));
8346                 }
8347
8348                 *r->out.data_needed = val->data_length;
8349
8350                 result = WERR_OK;
8351         }
8352
8353         return result;
8354 }
8355
8356 /****************************************************************
8357  _spoolss_SetPrinterData
8358 ****************************************************************/
8359
8360 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8361                                struct spoolss_SetPrinterData *r)
8362 {
8363         struct spoolss_SetPrinterDataEx r2;
8364
8365         r2.in.handle            = r->in.handle;
8366         r2.in.key_name          = "PrinterDriverData";
8367         r2.in.value_name        = r->in.value_name;
8368         r2.in.type              = r->in.type;
8369         r2.in.data              = r->in.data;
8370         r2.in.offered           = r->in.offered;
8371
8372         return _spoolss_SetPrinterDataEx(p, &r2);
8373 }
8374
8375 /****************************************************************
8376  _spoolss_ResetPrinter
8377 ****************************************************************/
8378
8379 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8380                              struct spoolss_ResetPrinter *r)
8381 {
8382         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8383         int             snum;
8384
8385         DEBUG(5,("_spoolss_ResetPrinter\n"));
8386
8387         /*
8388          * All we do is to check to see if the handle and queue is valid.
8389          * This call really doesn't mean anything to us because we only
8390          * support RAW printing.   --jerry
8391          */
8392
8393         if (!Printer) {
8394                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8395                         OUR_HANDLE(r->in.handle)));
8396                 return WERR_BADFID;
8397         }
8398
8399         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8400                 return WERR_BADFID;
8401
8402
8403         /* blindly return success */
8404         return WERR_OK;
8405 }
8406
8407 /****************************************************************
8408  _spoolss_DeletePrinterData
8409 ****************************************************************/
8410
8411 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8412                                   struct spoolss_DeletePrinterData *r)
8413 {
8414         struct spoolss_DeletePrinterDataEx r2;
8415
8416         r2.in.handle            = r->in.handle;
8417         r2.in.key_name          = "PrinterDriverData";
8418         r2.in.value_name        = r->in.value_name;
8419
8420         return _spoolss_DeletePrinterDataEx(p, &r2);
8421 }
8422
8423 /****************************************************************
8424  _spoolss_AddForm
8425 ****************************************************************/
8426
8427 WERROR _spoolss_AddForm(struct pipes_struct *p,
8428                         struct spoolss_AddForm *r)
8429 {
8430         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8431         int snum = -1;
8432         WERROR status = WERR_OK;
8433
8434         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8435
8436         DEBUG(5,("_spoolss_AddForm\n"));
8437
8438         if (!Printer) {
8439                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8440                         OUR_HANDLE(r->in.handle)));
8441                 return WERR_BADFID;
8442         }
8443
8444         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8445            and not a printer admin, then fail */
8446
8447         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8448             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8449             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8450                                           p->session_info->info3->base.domain.string,
8451                                           NULL,
8452                                           p->session_info->security_token,
8453                                           lp_printer_admin(snum))) {
8454                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8455                 return WERR_ACCESS_DENIED;
8456         }
8457
8458         switch (form->flags) {
8459         case SPOOLSS_FORM_USER:
8460         case SPOOLSS_FORM_BUILTIN:
8461         case SPOOLSS_FORM_PRINTER:
8462                 break;
8463         default:
8464                 return WERR_INVALID_PARAM;
8465         }
8466
8467         status = winreg_printer_addform1(p->mem_ctx,
8468                                          get_session_info_system(),
8469                                          p->msg_ctx,
8470                                          form);
8471         if (!W_ERROR_IS_OK(status)) {
8472                 return status;
8473         }
8474
8475         /*
8476          * ChangeID must always be set if this is a printer
8477          */
8478         if (Printer->printer_type == SPLHND_PRINTER) {
8479                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8480                         return WERR_BADFID;
8481                 }
8482
8483                 status = winreg_printer_update_changeid(p->mem_ctx,
8484                                                         get_session_info_system(),
8485                                                         p->msg_ctx,
8486                                                         lp_const_servicename(snum));
8487                 if (!W_ERROR_IS_OK(status)) {
8488                         return status;
8489                 }
8490         }
8491
8492         return status;
8493 }
8494
8495 /****************************************************************
8496  _spoolss_DeleteForm
8497 ****************************************************************/
8498
8499 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8500                            struct spoolss_DeleteForm *r)
8501 {
8502         const char *form_name = r->in.form_name;
8503         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8504         int snum = -1;
8505         WERROR status = WERR_OK;
8506
8507         DEBUG(5,("_spoolss_DeleteForm\n"));
8508
8509         if (!Printer) {
8510                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8511                         OUR_HANDLE(r->in.handle)));
8512                 return WERR_BADFID;
8513         }
8514
8515         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8516             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8517             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8518                                           p->session_info->info3->base.domain.string,
8519                                           NULL,
8520                                           p->session_info->security_token,
8521                                           lp_printer_admin(snum))) {
8522                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8523                 return WERR_ACCESS_DENIED;
8524         }
8525
8526         status = winreg_printer_deleteform1(p->mem_ctx,
8527                                             get_session_info_system(),
8528                                             p->msg_ctx,
8529                                             form_name);
8530         if (!W_ERROR_IS_OK(status)) {
8531                 return status;
8532         }
8533
8534         /*
8535          * ChangeID must always be set if this is a printer
8536          */
8537         if (Printer->printer_type == SPLHND_PRINTER) {
8538                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8539                         return WERR_BADFID;
8540                 }
8541
8542                 status = winreg_printer_update_changeid(p->mem_ctx,
8543                                                         get_session_info_system(),
8544                                                         p->msg_ctx,
8545                                                         lp_const_servicename(snum));
8546                 if (!W_ERROR_IS_OK(status)) {
8547                         return status;
8548                 }
8549         }
8550
8551         return status;
8552 }
8553
8554 /****************************************************************
8555  _spoolss_SetForm
8556 ****************************************************************/
8557
8558 WERROR _spoolss_SetForm(struct pipes_struct *p,
8559                         struct spoolss_SetForm *r)
8560 {
8561         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8562         const char *form_name = r->in.form_name;
8563         int snum = -1;
8564         WERROR status = WERR_OK;
8565
8566         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8567
8568         DEBUG(5,("_spoolss_SetForm\n"));
8569
8570         if (!Printer) {
8571                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8572                         OUR_HANDLE(r->in.handle)));
8573                 return WERR_BADFID;
8574         }
8575
8576         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8577            and not a printer admin, then fail */
8578
8579         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8580              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8581              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8582                                           p->session_info->info3->base.domain.string,
8583                                           NULL,
8584                                           p->session_info->security_token,
8585                                           lp_printer_admin(snum))) {
8586                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8587                 return WERR_ACCESS_DENIED;
8588         }
8589
8590         status = winreg_printer_setform1(p->mem_ctx,
8591                                          get_session_info_system(),
8592                                          p->msg_ctx,
8593                                          form_name,
8594                                          form);
8595         if (!W_ERROR_IS_OK(status)) {
8596                 return status;
8597         }
8598
8599         /*
8600          * ChangeID must always be set if this is a printer
8601          */
8602         if (Printer->printer_type == SPLHND_PRINTER) {
8603                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8604                         return WERR_BADFID;
8605                 }
8606
8607                 status = winreg_printer_update_changeid(p->mem_ctx,
8608                                                         get_session_info_system(),
8609                                                         p->msg_ctx,
8610                                                         lp_const_servicename(snum));
8611                 if (!W_ERROR_IS_OK(status)) {
8612                         return status;
8613                 }
8614         }
8615
8616         return status;
8617 }
8618
8619 /****************************************************************************
8620  fill_print_processor1
8621 ****************************************************************************/
8622
8623 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8624                                     struct spoolss_PrintProcessorInfo1 *r,
8625                                     const char *print_processor_name)
8626 {
8627         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8628         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8629
8630         return WERR_OK;
8631 }
8632
8633 /****************************************************************************
8634  enumprintprocessors level 1.
8635 ****************************************************************************/
8636
8637 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8638                                           union spoolss_PrintProcessorInfo **info_p,
8639                                           uint32_t *count)
8640 {
8641         union spoolss_PrintProcessorInfo *info;
8642         WERROR result;
8643
8644         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8645         W_ERROR_HAVE_NO_MEMORY(info);
8646
8647         *count = 1;
8648
8649         result = fill_print_processor1(info, &info[0].info1, "winprint");
8650         if (!W_ERROR_IS_OK(result)) {
8651                 goto out;
8652         }
8653
8654  out:
8655         if (!W_ERROR_IS_OK(result)) {
8656                 TALLOC_FREE(info);
8657                 *count = 0;
8658                 return result;
8659         }
8660
8661         *info_p = info;
8662
8663         return WERR_OK;
8664 }
8665
8666 /****************************************************************
8667  _spoolss_EnumPrintProcessors
8668 ****************************************************************/
8669
8670 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8671                                     struct spoolss_EnumPrintProcessors *r)
8672 {
8673         WERROR result;
8674
8675         /* that's an [in out] buffer */
8676
8677         if (!r->in.buffer && (r->in.offered != 0)) {
8678                 return WERR_INVALID_PARAM;
8679         }
8680
8681         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8682
8683         /*
8684          * Enumerate the print processors ...
8685          *
8686          * Just reply with "winprint", to keep NT happy
8687          * and I can use my nice printer checker.
8688          */
8689
8690         *r->out.count = 0;
8691         *r->out.needed = 0;
8692         *r->out.info = NULL;
8693
8694         if (!get_short_archi(r->in.environment)) {
8695                 return WERR_INVALID_ENVIRONMENT;
8696         }
8697
8698         switch (r->in.level) {
8699         case 1:
8700                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8701                                                      r->out.count);
8702                 break;
8703         default:
8704                 return WERR_UNKNOWN_LEVEL;
8705         }
8706
8707         if (!W_ERROR_IS_OK(result)) {
8708                 return result;
8709         }
8710
8711         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8712                                                      spoolss_EnumPrintProcessors,
8713                                                      *r->out.info, r->in.level,
8714                                                      *r->out.count);
8715         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8716         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8717
8718         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8719 }
8720
8721 /****************************************************************************
8722  fill_printprocdatatype1
8723 ****************************************************************************/
8724
8725 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8726                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8727                                       const char *name_array)
8728 {
8729         r->name_array = talloc_strdup(mem_ctx, name_array);
8730         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8731
8732         return WERR_OK;
8733 }
8734
8735 /****************************************************************************
8736  enumprintprocdatatypes level 1.
8737 ****************************************************************************/
8738
8739 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8740                                              union spoolss_PrintProcDataTypesInfo **info_p,
8741                                              uint32_t *count)
8742 {
8743         WERROR result;
8744         union spoolss_PrintProcDataTypesInfo *info;
8745
8746         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8747         W_ERROR_HAVE_NO_MEMORY(info);
8748
8749         *count = 1;
8750
8751         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8752         if (!W_ERROR_IS_OK(result)) {
8753                 goto out;
8754         }
8755
8756  out:
8757         if (!W_ERROR_IS_OK(result)) {
8758                 TALLOC_FREE(info);
8759                 *count = 0;
8760                 return result;
8761         }
8762
8763         *info_p = info;
8764
8765         return WERR_OK;
8766 }
8767
8768 /****************************************************************
8769  _spoolss_EnumPrintProcDataTypes
8770 ****************************************************************/
8771
8772 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8773                                        struct spoolss_EnumPrintProcDataTypes *r)
8774 {
8775         WERROR result;
8776
8777         /* that's an [in out] buffer */
8778
8779         if (!r->in.buffer && (r->in.offered != 0)) {
8780                 return WERR_INVALID_PARAM;
8781         }
8782
8783         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8784
8785         *r->out.count = 0;
8786         *r->out.needed = 0;
8787         *r->out.info = NULL;
8788
8789         if (r->in.print_processor_name == NULL ||
8790             !strequal(r->in.print_processor_name, "winprint")) {
8791                 return WERR_UNKNOWN_PRINTPROCESSOR;
8792         }
8793
8794         switch (r->in.level) {
8795         case 1:
8796                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8797                                                         r->out.count);
8798                 break;
8799         default:
8800                 return WERR_UNKNOWN_LEVEL;
8801         }
8802
8803         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8804                                                      spoolss_EnumPrintProcDataTypes,
8805                                                      *r->out.info, r->in.level,
8806                                                      *r->out.count);
8807         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8808         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8809
8810         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8811 }
8812
8813 /****************************************************************************
8814  fill_monitor_1
8815 ****************************************************************************/
8816
8817 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8818                              struct spoolss_MonitorInfo1 *r,
8819                              const char *monitor_name)
8820 {
8821         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8822         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8823
8824         return WERR_OK;
8825 }
8826
8827 /****************************************************************************
8828  fill_monitor_2
8829 ****************************************************************************/
8830
8831 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8832                              struct spoolss_MonitorInfo2 *r,
8833                              const char *monitor_name,
8834                              const char *environment,
8835                              const char *dll_name)
8836 {
8837         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8838         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8839         r->environment                  = talloc_strdup(mem_ctx, environment);
8840         W_ERROR_HAVE_NO_MEMORY(r->environment);
8841         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8842         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8843
8844         return WERR_OK;
8845 }
8846
8847 /****************************************************************************
8848  enumprintmonitors level 1.
8849 ****************************************************************************/
8850
8851 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8852                                         union spoolss_MonitorInfo **info_p,
8853                                         uint32_t *count)
8854 {
8855         union spoolss_MonitorInfo *info;
8856         WERROR result = WERR_OK;
8857
8858         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8859         W_ERROR_HAVE_NO_MEMORY(info);
8860
8861         *count = 2;
8862
8863         result = fill_monitor_1(info, &info[0].info1,
8864                                 SPL_LOCAL_PORT);
8865         if (!W_ERROR_IS_OK(result)) {
8866                 goto out;
8867         }
8868
8869         result = fill_monitor_1(info, &info[1].info1,
8870                                 SPL_TCPIP_PORT);
8871         if (!W_ERROR_IS_OK(result)) {
8872                 goto out;
8873         }
8874
8875 out:
8876         if (!W_ERROR_IS_OK(result)) {
8877                 TALLOC_FREE(info);
8878                 *count = 0;
8879                 return result;
8880         }
8881
8882         *info_p = info;
8883
8884         return WERR_OK;
8885 }
8886
8887 /****************************************************************************
8888  enumprintmonitors level 2.
8889 ****************************************************************************/
8890
8891 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8892                                         union spoolss_MonitorInfo **info_p,
8893                                         uint32_t *count)
8894 {
8895         union spoolss_MonitorInfo *info;
8896         WERROR result = WERR_OK;
8897
8898         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8899         W_ERROR_HAVE_NO_MEMORY(info);
8900
8901         *count = 2;
8902
8903         result = fill_monitor_2(info, &info[0].info2,
8904                                 SPL_LOCAL_PORT,
8905                                 "Windows NT X86", /* FIXME */
8906                                 "localmon.dll");
8907         if (!W_ERROR_IS_OK(result)) {
8908                 goto out;
8909         }
8910
8911         result = fill_monitor_2(info, &info[1].info2,
8912                                 SPL_TCPIP_PORT,
8913                                 "Windows NT X86", /* FIXME */
8914                                 "tcpmon.dll");
8915         if (!W_ERROR_IS_OK(result)) {
8916                 goto out;
8917         }
8918
8919 out:
8920         if (!W_ERROR_IS_OK(result)) {
8921                 TALLOC_FREE(info);
8922                 *count = 0;
8923                 return result;
8924         }
8925
8926         *info_p = info;
8927
8928         return WERR_OK;
8929 }
8930
8931 /****************************************************************
8932  _spoolss_EnumMonitors
8933 ****************************************************************/
8934
8935 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8936                              struct spoolss_EnumMonitors *r)
8937 {
8938         WERROR result;
8939
8940         /* that's an [in out] buffer */
8941
8942         if (!r->in.buffer && (r->in.offered != 0)) {
8943                 return WERR_INVALID_PARAM;
8944         }
8945
8946         DEBUG(5,("_spoolss_EnumMonitors\n"));
8947
8948         /*
8949          * Enumerate the print monitors ...
8950          *
8951          * Just reply with "Local Port", to keep NT happy
8952          * and I can use my nice printer checker.
8953          */
8954
8955         *r->out.count = 0;
8956         *r->out.needed = 0;
8957         *r->out.info = NULL;
8958
8959         switch (r->in.level) {
8960         case 1:
8961                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8962                                                    r->out.count);
8963                 break;
8964         case 2:
8965                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8966                                                    r->out.count);
8967                 break;
8968         default:
8969                 return WERR_UNKNOWN_LEVEL;
8970         }
8971
8972         if (!W_ERROR_IS_OK(result)) {
8973                 return result;
8974         }
8975
8976         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8977                                                      spoolss_EnumMonitors,
8978                                                      *r->out.info, r->in.level,
8979                                                      *r->out.count);
8980         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8981         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8982
8983         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8984 }
8985
8986 /****************************************************************************
8987 ****************************************************************************/
8988
8989 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8990                              const print_queue_struct *queue,
8991                              int count, int snum,
8992                              struct spoolss_PrinterInfo2 *pinfo2,
8993                              uint32_t jobid,
8994                              struct spoolss_JobInfo1 *r)
8995 {
8996         int i = 0;
8997         bool found = false;
8998
8999         for (i=0; i<count; i++) {
9000                 if (queue[i].job == (int)jobid) {
9001                         found = true;
9002                         break;
9003                 }
9004         }
9005
9006         if (found == false) {
9007                 /* NT treats not found as bad param... yet another bad choice */
9008                 return WERR_INVALID_PARAM;
9009         }
9010
9011         return fill_job_info1(mem_ctx,
9012                               r,
9013                               &queue[i],
9014                               i,
9015                               snum,
9016                               pinfo2);
9017 }
9018
9019 /****************************************************************************
9020 ****************************************************************************/
9021
9022 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9023                              const print_queue_struct *queue,
9024                              int count, int snum,
9025                              struct spoolss_PrinterInfo2 *pinfo2,
9026                              uint32_t jobid,
9027                              struct spoolss_JobInfo2 *r)
9028 {
9029         int i = 0;
9030         bool found = false;
9031         struct spoolss_DeviceMode *devmode;
9032         WERROR result;
9033
9034         for (i=0; i<count; i++) {
9035                 if (queue[i].job == (int)jobid) {
9036                         found = true;
9037                         break;
9038                 }
9039         }
9040
9041         if (found == false) {
9042                 /* NT treats not found as bad param... yet another bad
9043                    choice */
9044                 return WERR_INVALID_PARAM;
9045         }
9046
9047         /*
9048          * if the print job does not have a DEVMODE associated with it,
9049          * just use the one for the printer. A NULL devicemode is not
9050          *  a failure condition
9051          */
9052
9053         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9054         if (!devmode) {
9055                 result = spoolss_create_default_devmode(mem_ctx,
9056                                                 pinfo2->printername,
9057                                                 &devmode);
9058                 if (!W_ERROR_IS_OK(result)) {
9059                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9060                         return result;
9061                 }
9062         }
9063
9064         return fill_job_info2(mem_ctx,
9065                               r,
9066                               &queue[i],
9067                               i,
9068                               snum,
9069                               pinfo2,
9070                               devmode);
9071 }
9072
9073 /****************************************************************
9074  _spoolss_GetJob
9075 ****************************************************************/
9076
9077 WERROR _spoolss_GetJob(struct pipes_struct *p,
9078                        struct spoolss_GetJob *r)
9079 {
9080         WERROR result = WERR_OK;
9081         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9082         int snum;
9083         int count;
9084         print_queue_struct      *queue = NULL;
9085         print_status_struct prt_status;
9086
9087         /* that's an [in out] buffer */
9088
9089         if (!r->in.buffer && (r->in.offered != 0)) {
9090                 return WERR_INVALID_PARAM;
9091         }
9092
9093         DEBUG(5,("_spoolss_GetJob\n"));
9094
9095         *r->out.needed = 0;
9096
9097         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9098                 return WERR_BADFID;
9099         }
9100
9101         result = winreg_get_printer(p->mem_ctx,
9102                                     get_session_info_system(),
9103                                     p->msg_ctx,
9104                                     lp_const_servicename(snum),
9105                                     &pinfo2);
9106         if (!W_ERROR_IS_OK(result)) {
9107                 return result;
9108         }
9109
9110         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9111
9112         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9113                      count, prt_status.status, prt_status.message));
9114
9115         switch (r->in.level) {
9116         case 1:
9117                 result = getjob_level_1(p->mem_ctx,
9118                                         queue, count, snum, pinfo2,
9119                                         r->in.job_id, &r->out.info->info1);
9120                 break;
9121         case 2:
9122                 result = getjob_level_2(p->mem_ctx,
9123                                         queue, count, snum, pinfo2,
9124                                         r->in.job_id, &r->out.info->info2);
9125                 break;
9126         default:
9127                 result = WERR_UNKNOWN_LEVEL;
9128                 break;
9129         }
9130
9131         SAFE_FREE(queue);
9132         TALLOC_FREE(pinfo2);
9133
9134         if (!W_ERROR_IS_OK(result)) {
9135                 TALLOC_FREE(r->out.info);
9136                 return result;
9137         }
9138
9139         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9140                                                                                    r->in.level);
9141         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9142
9143         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9144 }
9145
9146 /****************************************************************
9147  _spoolss_GetPrinterDataEx
9148 ****************************************************************/
9149
9150 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9151                                  struct spoolss_GetPrinterDataEx *r)
9152 {
9153
9154         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9155         const char *printer;
9156         int                     snum = 0;
9157         WERROR result = WERR_OK;
9158         DATA_BLOB blob;
9159         enum winreg_Type val_type;
9160         uint8_t *val_data;
9161         uint32_t val_size;
9162
9163
9164         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9165
9166         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9167                 r->in.key_name, r->in.value_name));
9168
9169         /* in case of problem, return some default values */
9170
9171         *r->out.needed  = 0;
9172         *r->out.type    = REG_NONE;
9173
9174         if (!Printer) {
9175                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9176                         OUR_HANDLE(r->in.handle)));
9177                 result = WERR_BADFID;
9178                 goto done;
9179         }
9180
9181         /* Is the handle to a printer or to the server? */
9182
9183         if (Printer->printer_type == SPLHND_SERVER) {
9184
9185                 union spoolss_PrinterData data;
9186
9187                 result = getprinterdata_printer_server(p->mem_ctx,
9188                                                        r->in.value_name,
9189                                                        r->out.type,
9190                                                        &data);
9191                 if (!W_ERROR_IS_OK(result)) {
9192                         return result;
9193                 }
9194
9195                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9196                                                   *r->out.type, &data);
9197                 if (!W_ERROR_IS_OK(result)) {
9198                         return result;
9199                 }
9200
9201                 *r->out.needed = blob.length;
9202
9203                 if (r->in.offered >= *r->out.needed) {
9204                         memcpy(r->out.data, blob.data, blob.length);
9205                 }
9206
9207                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9208         }
9209
9210         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9211                 return WERR_BADFID;
9212         }
9213         printer = lp_const_servicename(snum);
9214
9215         /* check to see if the keyname is valid */
9216         if (!strlen(r->in.key_name)) {
9217                 return WERR_INVALID_PARAM;
9218         }
9219
9220         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9221         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9222             strequal(r->in.value_name, "ChangeId")) {
9223                 *r->out.type = REG_DWORD;
9224                 *r->out.needed = 4;
9225                 if (r->in.offered >= *r->out.needed) {
9226                         uint32_t changeid = 0;
9227
9228                         result = winreg_printer_get_changeid(p->mem_ctx,
9229                                                              get_session_info_system(),
9230                                                              p->msg_ctx,
9231                                                              printer,
9232                                                              &changeid);
9233                         if (!W_ERROR_IS_OK(result)) {
9234                                 return result;
9235                         }
9236
9237                         SIVAL(r->out.data, 0, changeid);
9238                         result = WERR_OK;
9239                 }
9240                 goto done;
9241         }
9242
9243         result = winreg_get_printer_dataex(p->mem_ctx,
9244                                            get_session_info_system(),
9245                                            p->msg_ctx,
9246                                            printer,
9247                                            r->in.key_name,
9248                                            r->in.value_name,
9249                                            &val_type,
9250                                            &val_data,
9251                                            &val_size);
9252         if (!W_ERROR_IS_OK(result)) {
9253                 return result;
9254         }
9255
9256         *r->out.needed = val_size;
9257         *r->out.type = val_type;
9258
9259         if (r->in.offered >= *r->out.needed) {
9260                 memcpy(r->out.data, val_data, val_size);
9261         }
9262
9263  done:
9264         /* retain type when returning WERR_MORE_DATA */
9265         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9266
9267         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9268 }
9269
9270 /****************************************************************
9271  _spoolss_SetPrinterDataEx
9272 ****************************************************************/
9273
9274 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9275                                  struct spoolss_SetPrinterDataEx *r)
9276 {
9277         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9278         int                     snum = 0;
9279         WERROR                  result = WERR_OK;
9280         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9281         char                    *oid_string;
9282
9283         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9284
9285         /* From MSDN documentation of SetPrinterDataEx: pass request to
9286            SetPrinterData if key is "PrinterDriverData" */
9287
9288         if (!Printer) {
9289                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9290                         OUR_HANDLE(r->in.handle)));
9291                 return WERR_BADFID;
9292         }
9293
9294         if (Printer->printer_type == SPLHND_SERVER) {
9295                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9296                         "Not implemented for server handles yet\n"));
9297                 return WERR_INVALID_PARAM;
9298         }
9299
9300         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9301                 return WERR_BADFID;
9302         }
9303
9304         /*
9305          * Access check : NT returns "access denied" if you make a
9306          * SetPrinterData call without the necessary privildge.
9307          * we were originally returning OK if nothing changed
9308          * which made Win2k issue **a lot** of SetPrinterData
9309          * when connecting to a printer  --jerry
9310          */
9311
9312         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9313                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9314                         "change denied by handle access permissions\n"));
9315                 return WERR_ACCESS_DENIED;
9316         }
9317
9318         result = winreg_get_printer(Printer,
9319                                     get_session_info_system(),
9320                                     p->msg_ctx,
9321                                     lp_servicename(snum),
9322                                     &pinfo2);
9323         if (!W_ERROR_IS_OK(result)) {
9324                 return result;
9325         }
9326
9327         /* check for OID in valuename */
9328
9329         oid_string = strchr(r->in.value_name, ',');
9330         if (oid_string) {
9331                 *oid_string = '\0';
9332                 oid_string++;
9333         }
9334
9335         /* save the registry data */
9336
9337         result = winreg_set_printer_dataex(p->mem_ctx,
9338                                            get_session_info_system(),
9339                                            p->msg_ctx,
9340                                            pinfo2->sharename,
9341                                            r->in.key_name,
9342                                            r->in.value_name,
9343                                            r->in.type,
9344                                            r->in.data,
9345                                            r->in.offered);
9346
9347         if (W_ERROR_IS_OK(result)) {
9348                 /* save the OID if one was specified */
9349                 if (oid_string) {
9350                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9351                                 r->in.key_name, SPOOL_OID_KEY);
9352                         if (!str) {
9353                                 result = WERR_NOMEM;
9354                                 goto done;
9355                         }
9356
9357                         /*
9358                          * I'm not checking the status here on purpose.  Don't know
9359                          * if this is right, but I'm returning the status from the
9360                          * previous set_printer_dataex() call.  I have no idea if
9361                          * this is right.    --jerry
9362                          */
9363                         winreg_set_printer_dataex(p->mem_ctx,
9364                                                   get_session_info_system(),
9365                                                   p->msg_ctx,
9366                                                   pinfo2->sharename,
9367                                                   str,
9368                                                   r->in.value_name,
9369                                                   REG_SZ,
9370                                                   (uint8_t *) oid_string,
9371                                                   strlen(oid_string) + 1);
9372                 }
9373
9374                 result = winreg_printer_update_changeid(p->mem_ctx,
9375                                                         get_session_info_system(),
9376                                                         p->msg_ctx,
9377                                                         lp_const_servicename(snum));
9378
9379         }
9380
9381 done:
9382         talloc_free(pinfo2);
9383         return result;
9384 }
9385
9386 /****************************************************************
9387  _spoolss_DeletePrinterDataEx
9388 ****************************************************************/
9389
9390 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9391                                     struct spoolss_DeletePrinterDataEx *r)
9392 {
9393         const char *printer;
9394         int             snum=0;
9395         WERROR          status = WERR_OK;
9396         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9397
9398         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9399
9400         if (!Printer) {
9401                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9402                         "Invalid handle (%s:%u:%u).\n",
9403                         OUR_HANDLE(r->in.handle)));
9404                 return WERR_BADFID;
9405         }
9406
9407         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9408                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9409                         "printer properties change denied by handle\n"));
9410                 return WERR_ACCESS_DENIED;
9411         }
9412
9413         if (!r->in.value_name || !r->in.key_name) {
9414                 return WERR_NOMEM;
9415         }
9416
9417         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9418                 return WERR_BADFID;
9419         }
9420         printer = lp_const_servicename(snum);
9421
9422         status = winreg_delete_printer_dataex(p->mem_ctx,
9423                                               get_session_info_system(),
9424                                               p->msg_ctx,
9425                                               printer,
9426                                               r->in.key_name,
9427                                               r->in.value_name);
9428         if (W_ERROR_IS_OK(status)) {
9429                 status = winreg_printer_update_changeid(p->mem_ctx,
9430                                                         get_session_info_system(),
9431                                                         p->msg_ctx,
9432                                                         printer);
9433         }
9434
9435         return status;
9436 }
9437
9438 /****************************************************************
9439  _spoolss_EnumPrinterKey
9440 ****************************************************************/
9441
9442 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9443                                struct spoolss_EnumPrinterKey *r)
9444 {
9445         uint32_t        num_keys;
9446         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9447         int             snum = 0;
9448         WERROR          result = WERR_BADFILE;
9449         const char **array = NULL;
9450         DATA_BLOB blob;
9451
9452         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9453
9454         if (!Printer) {
9455                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9456                         OUR_HANDLE(r->in.handle)));
9457                 return WERR_BADFID;
9458         }
9459
9460         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9461                 return WERR_BADFID;
9462         }
9463
9464         result = winreg_enum_printer_key(p->mem_ctx,
9465                                          get_session_info_system(),
9466                                          p->msg_ctx,
9467                                          lp_const_servicename(snum),
9468                                          r->in.key_name,
9469                                          &num_keys,
9470                                          &array);
9471         if (!W_ERROR_IS_OK(result)) {
9472                 goto done;
9473         }
9474
9475         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9476                 result = WERR_NOMEM;
9477                 goto done;
9478         }
9479
9480         *r->out._ndr_size = r->in.offered / 2;
9481         *r->out.needed = blob.length;
9482
9483         if (r->in.offered < *r->out.needed) {
9484                 result = WERR_MORE_DATA;
9485         } else {
9486                 result = WERR_OK;
9487                 r->out.key_buffer->string_array = array;
9488         }
9489
9490  done:
9491         if (!W_ERROR_IS_OK(result)) {
9492                 TALLOC_FREE(array);
9493                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9494                         *r->out.needed = 0;
9495                 }
9496         }
9497
9498         return result;
9499 }
9500
9501 /****************************************************************
9502  _spoolss_DeletePrinterKey
9503 ****************************************************************/
9504
9505 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9506                                  struct spoolss_DeletePrinterKey *r)
9507 {
9508         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9509         int                     snum=0;
9510         WERROR                  status;
9511         const char *printer;
9512
9513         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9514
9515         if (!Printer) {
9516                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9517                         OUR_HANDLE(r->in.handle)));
9518                 return WERR_BADFID;
9519         }
9520
9521         /* if keyname == NULL, return error */
9522         if ( !r->in.key_name )
9523                 return WERR_INVALID_PARAM;
9524
9525         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9526                 return WERR_BADFID;
9527         }
9528
9529         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9530                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9531                         "printer properties change denied by handle\n"));
9532                 return WERR_ACCESS_DENIED;
9533         }
9534
9535         printer = lp_const_servicename(snum);
9536
9537         /* delete the key and all subkeys */
9538         status = winreg_delete_printer_key(p->mem_ctx,
9539                                            get_session_info_system(),
9540                                            p->msg_ctx,
9541                                            printer,
9542                                            r->in.key_name);
9543         if (W_ERROR_IS_OK(status)) {
9544                 status = winreg_printer_update_changeid(p->mem_ctx,
9545                                                         get_session_info_system(),
9546                                                         p->msg_ctx,
9547                                                         printer);
9548         }
9549
9550         return status;
9551 }
9552
9553 /****************************************************************
9554  _spoolss_EnumPrinterDataEx
9555 ****************************************************************/
9556
9557 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9558                                   struct spoolss_EnumPrinterDataEx *r)
9559 {
9560         uint32_t        count = 0;
9561         struct spoolss_PrinterEnumValues *info = NULL;
9562         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9563         int             snum;
9564         WERROR          result;
9565
9566         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9567
9568         *r->out.count = 0;
9569         *r->out.needed = 0;
9570         *r->out.info = NULL;
9571
9572         if (!Printer) {
9573                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9574                         OUR_HANDLE(r->in.handle)));
9575                 return WERR_BADFID;
9576         }
9577
9578         /*
9579          * first check for a keyname of NULL or "".  Win2k seems to send
9580          * this a lot and we should send back WERR_INVALID_PARAM
9581          * no need to spend time looking up the printer in this case.
9582          * --jerry
9583          */
9584
9585         if (!strlen(r->in.key_name)) {
9586                 result = WERR_INVALID_PARAM;
9587                 goto done;
9588         }
9589
9590         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9591                 return WERR_BADFID;
9592         }
9593
9594         /* now look for a match on the key name */
9595         result = winreg_enum_printer_dataex(p->mem_ctx,
9596                                             get_session_info_system(),
9597                                             p->msg_ctx,
9598                                             lp_const_servicename(snum),
9599                                             r->in.key_name,
9600                                             &count,
9601                                             &info);
9602         if (!W_ERROR_IS_OK(result)) {
9603                 goto done;
9604         }
9605
9606 #if 0 /* FIXME - gd */
9607         /* housekeeping information in the reply */
9608
9609         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9610          * the hand marshalled container size is a multiple
9611          * of 4 bytes for RPC alignment.
9612          */
9613
9614         if (needed % 4) {
9615                 needed += 4-(needed % 4);
9616         }
9617 #endif
9618         *r->out.count   = count;
9619         *r->out.info    = info;
9620
9621  done:
9622         if (!W_ERROR_IS_OK(result)) {
9623                 return result;
9624         }
9625
9626         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9627                                                spoolss_EnumPrinterDataEx,
9628                                                *r->out.info,
9629                                                *r->out.count);
9630         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9631         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9632
9633         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9634 }
9635
9636 /****************************************************************************
9637 ****************************************************************************/
9638
9639 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9640                                                  const char *servername,
9641                                                  const char *environment,
9642                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9643 {
9644         WERROR werr;
9645         char *path = NULL;
9646
9647         werr = compose_spoolss_server_path(mem_ctx,
9648                                            servername,
9649                                            environment,
9650                                            SPOOLSS_PRTPROCS_PATH,
9651                                            &path);
9652         if (!W_ERROR_IS_OK(werr)) {
9653                 return werr;
9654         }
9655
9656         DEBUG(4,("print processor directory: [%s]\n", path));
9657
9658         r->directory_name = path;
9659
9660         return WERR_OK;
9661 }
9662
9663 /****************************************************************
9664  _spoolss_GetPrintProcessorDirectory
9665 ****************************************************************/
9666
9667 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9668                                            struct spoolss_GetPrintProcessorDirectory *r)
9669 {
9670         WERROR result;
9671         char *prnproc_share = NULL;
9672         bool prnproc_share_exists = false;
9673         int snum;
9674
9675         /* that's an [in out] buffer */
9676
9677         if (!r->in.buffer && (r->in.offered != 0)) {
9678                 return WERR_INVALID_PARAM;
9679         }
9680
9681         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9682                 r->in.level));
9683
9684         *r->out.needed = 0;
9685
9686         /* r->in.level is ignored */
9687
9688         /* We always should reply with a local print processor directory so that
9689          * users are not forced to have a [prnproc$] share on the Samba spoolss
9690          * server, if users decide to do so, lets announce it though - Guenther */
9691
9692         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9693         if (!prnproc_share) {
9694                 return WERR_NOMEM;
9695         }
9696         if (snum != -1) {
9697                 prnproc_share_exists = true;
9698         }
9699
9700         result = getprintprocessordirectory_level_1(p->mem_ctx,
9701                                                     prnproc_share_exists ? r->in.server : NULL,
9702                                                     r->in.environment,
9703                                                     &r->out.info->info1);
9704         if (!W_ERROR_IS_OK(result)) {
9705                 TALLOC_FREE(r->out.info);
9706                 return result;
9707         }
9708
9709         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9710                                                                                    r->out.info, r->in.level);
9711         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9712
9713         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9714 }
9715
9716 /*******************************************************************
9717  ********************************************************************/
9718
9719 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9720                                const char *dllname)
9721 {
9722         enum ndr_err_code ndr_err;
9723         struct spoolss_MonitorUi ui;
9724
9725         ui.dll_name = dllname;
9726
9727         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9728                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9729         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9730                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9731         }
9732         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9733 }
9734
9735 /*******************************************************************
9736  Streams the monitor UI DLL name in UNICODE
9737 *******************************************************************/
9738
9739 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9740                                struct security_token *token, DATA_BLOB *in,
9741                                DATA_BLOB *out, uint32_t *needed)
9742 {
9743         const char *dllname = "tcpmonui.dll";
9744
9745         *needed = (strlen(dllname)+1) * 2;
9746
9747         if (out->length < *needed) {
9748                 return WERR_INSUFFICIENT_BUFFER;
9749         }
9750
9751         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9752                 return WERR_NOMEM;
9753         }
9754
9755         return WERR_OK;
9756 }
9757
9758 /*******************************************************************
9759  ********************************************************************/
9760
9761 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9762                              struct spoolss_PortData1 *port1,
9763                              const DATA_BLOB *buf)
9764 {
9765         enum ndr_err_code ndr_err;
9766         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9767                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9768         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9769                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9770         }
9771         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9772 }
9773
9774 /*******************************************************************
9775  ********************************************************************/
9776
9777 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9778                              struct spoolss_PortData2 *port2,
9779                              const DATA_BLOB *buf)
9780 {
9781         enum ndr_err_code ndr_err;
9782         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9783                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9784         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9785                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9786         }
9787         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9788 }
9789
9790 /*******************************************************************
9791  Create a new TCP/IP port
9792 *******************************************************************/
9793
9794 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9795                              struct security_token *token, DATA_BLOB *in,
9796                              DATA_BLOB *out, uint32_t *needed)
9797 {
9798         struct spoolss_PortData1 port1;
9799         struct spoolss_PortData2 port2;
9800         char *device_uri = NULL;
9801         uint32_t version;
9802
9803         const char *portname;
9804         const char *hostaddress;
9805         const char *queue;
9806         uint32_t port_number;
9807         uint32_t protocol;
9808
9809         /* peek for spoolss_PortData version */
9810
9811         if (!in || (in->length < (128 + 4))) {
9812                 return WERR_GENERAL_FAILURE;
9813         }
9814
9815         version = IVAL(in->data, 128);
9816
9817         switch (version) {
9818                 case 1:
9819                         ZERO_STRUCT(port1);
9820
9821                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9822                                 return WERR_NOMEM;
9823                         }
9824
9825                         portname        = port1.portname;
9826                         hostaddress     = port1.hostaddress;
9827                         queue           = port1.queue;
9828                         protocol        = port1.protocol;
9829                         port_number     = port1.port_number;
9830
9831                         break;
9832                 case 2:
9833                         ZERO_STRUCT(port2);
9834
9835                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9836                                 return WERR_NOMEM;
9837                         }
9838
9839                         portname        = port2.portname;
9840                         hostaddress     = port2.hostaddress;
9841                         queue           = port2.queue;
9842                         protocol        = port2.protocol;
9843                         port_number     = port2.port_number;
9844
9845                         break;
9846                 default:
9847                         DEBUG(1,("xcvtcp_addport: "
9848                                 "unknown version of port_data: %d\n", version));
9849                         return WERR_UNKNOWN_PORT;
9850         }
9851
9852         /* create the device URI and call the add_port_hook() */
9853
9854         switch (protocol) {
9855         case PROTOCOL_RAWTCP_TYPE:
9856                 device_uri = talloc_asprintf(mem_ctx,
9857                                 "socket://%s:%d/", hostaddress,
9858                                 port_number);
9859                 break;
9860
9861         case PROTOCOL_LPR_TYPE:
9862                 device_uri = talloc_asprintf(mem_ctx,
9863                         "lpr://%s/%s", hostaddress, queue );
9864                 break;
9865
9866         default:
9867                 return WERR_UNKNOWN_PORT;
9868         }
9869
9870         if (!device_uri) {
9871                 return WERR_NOMEM;
9872         }
9873
9874         return add_port_hook(mem_ctx, token, portname, device_uri);
9875 }
9876
9877 /*******************************************************************
9878 *******************************************************************/
9879
9880 struct xcv_api_table xcvtcp_cmds[] = {
9881         { "MonitorUI",  xcvtcp_monitorui },
9882         { "AddPort",    xcvtcp_addport},
9883         { NULL,         NULL }
9884 };
9885
9886 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9887                                      struct security_token *token, const char *command,
9888                                      DATA_BLOB *inbuf,
9889                                      DATA_BLOB *outbuf,
9890                                      uint32_t *needed )
9891 {
9892         int i;
9893
9894         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9895
9896         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9897                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9898                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9899         }
9900
9901         return WERR_BADFUNC;
9902 }
9903
9904 /*******************************************************************
9905 *******************************************************************/
9906 #if 0   /* don't support management using the "Local Port" monitor */
9907
9908 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9909                                  struct security_token *token, DATA_BLOB *in,
9910                                  DATA_BLOB *out, uint32_t *needed)
9911 {
9912         const char *dllname = "localui.dll";
9913
9914         *needed = (strlen(dllname)+1) * 2;
9915
9916         if (out->length < *needed) {
9917                 return WERR_INSUFFICIENT_BUFFER;
9918         }
9919
9920         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9921                 return WERR_NOMEM;
9922         }
9923
9924         return WERR_OK;
9925 }
9926
9927 /*******************************************************************
9928 *******************************************************************/
9929
9930 struct xcv_api_table xcvlocal_cmds[] = {
9931         { "MonitorUI",  xcvlocal_monitorui },
9932         { NULL,         NULL }
9933 };
9934 #else
9935 struct xcv_api_table xcvlocal_cmds[] = {
9936         { NULL,         NULL }
9937 };
9938 #endif
9939
9940
9941
9942 /*******************************************************************
9943 *******************************************************************/
9944
9945 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9946                                        struct security_token *token, const char *command,
9947                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9948                                        uint32_t *needed)
9949 {
9950         int i;
9951
9952         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9953
9954         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9955                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9956                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9957         }
9958         return WERR_BADFUNC;
9959 }
9960
9961 /****************************************************************
9962  _spoolss_XcvData
9963 ****************************************************************/
9964
9965 WERROR _spoolss_XcvData(struct pipes_struct *p,
9966                         struct spoolss_XcvData *r)
9967 {
9968         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9969         DATA_BLOB out_data = data_blob_null;
9970         WERROR werror;
9971
9972         if (!Printer) {
9973                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9974                         OUR_HANDLE(r->in.handle)));
9975                 return WERR_BADFID;
9976         }
9977
9978         /* Has to be a handle to the TCP/IP port monitor */
9979
9980         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9981                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9982                 return WERR_BADFID;
9983         }
9984
9985         /* requires administrative access to the server */
9986
9987         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9988                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9989                 return WERR_ACCESS_DENIED;
9990         }
9991
9992         /* Allocate the outgoing buffer */
9993
9994         if (r->in.out_data_size) {
9995                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9996                 if (out_data.data == NULL) {
9997                         return WERR_NOMEM;
9998                 }
9999         }
10000
10001         switch ( Printer->printer_type ) {
10002         case SPLHND_PORTMON_TCP:
10003                 werror = process_xcvtcp_command(p->mem_ctx,
10004                                                 p->session_info->security_token,
10005                                                 r->in.function_name,
10006                                                 &r->in.in_data, &out_data,
10007                                                 r->out.needed);
10008                 break;
10009         case SPLHND_PORTMON_LOCAL:
10010                 werror = process_xcvlocal_command(p->mem_ctx,
10011                                                   p->session_info->security_token,
10012                                                   r->in.function_name,
10013                                                   &r->in.in_data, &out_data,
10014                                                   r->out.needed);
10015                 break;
10016         default:
10017                 werror = WERR_INVALID_PRINT_MONITOR;
10018         }
10019
10020         if (!W_ERROR_IS_OK(werror)) {
10021                 return werror;
10022         }
10023
10024         *r->out.status_code = 0;
10025
10026         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10027                 memcpy(r->out.out_data, out_data.data,
10028                         MIN(r->in.out_data_size, out_data.length));
10029         }
10030
10031         return WERR_OK;
10032 }
10033
10034 /****************************************************************
10035  _spoolss_AddPrintProcessor
10036 ****************************************************************/
10037
10038 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10039                                   struct spoolss_AddPrintProcessor *r)
10040 {
10041         /* for now, just indicate success and ignore the add.  We'll
10042            automatically set the winprint processor for printer
10043            entries later.  Used to debug the LexMark Optra S 1855 PCL
10044            driver --jerry */
10045
10046         return WERR_OK;
10047 }
10048
10049 /****************************************************************
10050  _spoolss_AddPort
10051 ****************************************************************/
10052
10053 WERROR _spoolss_AddPort(struct pipes_struct *p,
10054                         struct spoolss_AddPort *r)
10055 {
10056         /* do what w2k3 does */
10057
10058         return WERR_NOT_SUPPORTED;
10059 }
10060
10061 /****************************************************************
10062  _spoolss_GetPrinterDriver
10063 ****************************************************************/
10064
10065 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10066                                  struct spoolss_GetPrinterDriver *r)
10067 {
10068         p->rng_fault_state = true;
10069         return WERR_NOT_SUPPORTED;
10070 }
10071
10072 /****************************************************************
10073  _spoolss_ReadPrinter
10074 ****************************************************************/
10075
10076 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10077                             struct spoolss_ReadPrinter *r)
10078 {
10079         p->rng_fault_state = true;
10080         return WERR_NOT_SUPPORTED;
10081 }
10082
10083 /****************************************************************
10084  _spoolss_WaitForPrinterChange
10085 ****************************************************************/
10086
10087 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10088                                      struct spoolss_WaitForPrinterChange *r)
10089 {
10090         p->rng_fault_state = true;
10091         return WERR_NOT_SUPPORTED;
10092 }
10093
10094 /****************************************************************
10095  _spoolss_ConfigurePort
10096 ****************************************************************/
10097
10098 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10099                               struct spoolss_ConfigurePort *r)
10100 {
10101         p->rng_fault_state = true;
10102         return WERR_NOT_SUPPORTED;
10103 }
10104
10105 /****************************************************************
10106  _spoolss_DeletePort
10107 ****************************************************************/
10108
10109 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10110                            struct spoolss_DeletePort *r)
10111 {
10112         p->rng_fault_state = true;
10113         return WERR_NOT_SUPPORTED;
10114 }
10115
10116 /****************************************************************
10117  _spoolss_CreatePrinterIC
10118 ****************************************************************/
10119
10120 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10121                                 struct spoolss_CreatePrinterIC *r)
10122 {
10123         p->rng_fault_state = true;
10124         return WERR_NOT_SUPPORTED;
10125 }
10126
10127 /****************************************************************
10128  _spoolss_PlayGDIScriptOnPrinterIC
10129 ****************************************************************/
10130
10131 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10132                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10133 {
10134         p->rng_fault_state = true;
10135         return WERR_NOT_SUPPORTED;
10136 }
10137
10138 /****************************************************************
10139  _spoolss_DeletePrinterIC
10140 ****************************************************************/
10141
10142 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10143                                 struct spoolss_DeletePrinterIC *r)
10144 {
10145         p->rng_fault_state = true;
10146         return WERR_NOT_SUPPORTED;
10147 }
10148
10149 /****************************************************************
10150  _spoolss_AddPrinterConnection
10151 ****************************************************************/
10152
10153 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10154                                      struct spoolss_AddPrinterConnection *r)
10155 {
10156         p->rng_fault_state = true;
10157         return WERR_NOT_SUPPORTED;
10158 }
10159
10160 /****************************************************************
10161  _spoolss_DeletePrinterConnection
10162 ****************************************************************/
10163
10164 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10165                                         struct spoolss_DeletePrinterConnection *r)
10166 {
10167         p->rng_fault_state = true;
10168         return WERR_NOT_SUPPORTED;
10169 }
10170
10171 /****************************************************************
10172  _spoolss_PrinterMessageBox
10173 ****************************************************************/
10174
10175 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10176                                   struct spoolss_PrinterMessageBox *r)
10177 {
10178         p->rng_fault_state = true;
10179         return WERR_NOT_SUPPORTED;
10180 }
10181
10182 /****************************************************************
10183  _spoolss_AddMonitor
10184 ****************************************************************/
10185
10186 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10187                            struct spoolss_AddMonitor *r)
10188 {
10189         p->rng_fault_state = true;
10190         return WERR_NOT_SUPPORTED;
10191 }
10192
10193 /****************************************************************
10194  _spoolss_DeleteMonitor
10195 ****************************************************************/
10196
10197 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10198                               struct spoolss_DeleteMonitor *r)
10199 {
10200         p->rng_fault_state = true;
10201         return WERR_NOT_SUPPORTED;
10202 }
10203
10204 /****************************************************************
10205  _spoolss_DeletePrintProcessor
10206 ****************************************************************/
10207
10208 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10209                                      struct spoolss_DeletePrintProcessor *r)
10210 {
10211         p->rng_fault_state = true;
10212         return WERR_NOT_SUPPORTED;
10213 }
10214
10215 /****************************************************************
10216  _spoolss_AddPrintProvidor
10217 ****************************************************************/
10218
10219 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10220                                  struct spoolss_AddPrintProvidor *r)
10221 {
10222         p->rng_fault_state = true;
10223         return WERR_NOT_SUPPORTED;
10224 }
10225
10226 /****************************************************************
10227  _spoolss_DeletePrintProvidor
10228 ****************************************************************/
10229
10230 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10231                                     struct spoolss_DeletePrintProvidor *r)
10232 {
10233         p->rng_fault_state = true;
10234         return WERR_NOT_SUPPORTED;
10235 }
10236
10237 /****************************************************************
10238  _spoolss_FindFirstPrinterChangeNotification
10239 ****************************************************************/
10240
10241 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10242                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10243 {
10244         p->rng_fault_state = true;
10245         return WERR_NOT_SUPPORTED;
10246 }
10247
10248 /****************************************************************
10249  _spoolss_FindNextPrinterChangeNotification
10250 ****************************************************************/
10251
10252 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10253                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10254 {
10255         p->rng_fault_state = true;
10256         return WERR_NOT_SUPPORTED;
10257 }
10258
10259 /****************************************************************
10260  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10261 ****************************************************************/
10262
10263 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10264                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10265 {
10266         p->rng_fault_state = true;
10267         return WERR_NOT_SUPPORTED;
10268 }
10269
10270 /****************************************************************
10271  _spoolss_ReplyOpenPrinter
10272 ****************************************************************/
10273
10274 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10275                                  struct spoolss_ReplyOpenPrinter *r)
10276 {
10277         p->rng_fault_state = true;
10278         return WERR_NOT_SUPPORTED;
10279 }
10280
10281 /****************************************************************
10282  _spoolss_RouterReplyPrinter
10283 ****************************************************************/
10284
10285 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10286                                    struct spoolss_RouterReplyPrinter *r)
10287 {
10288         p->rng_fault_state = true;
10289         return WERR_NOT_SUPPORTED;
10290 }
10291
10292 /****************************************************************
10293  _spoolss_ReplyClosePrinter
10294 ****************************************************************/
10295
10296 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10297                                   struct spoolss_ReplyClosePrinter *r)
10298 {
10299         p->rng_fault_state = true;
10300         return WERR_NOT_SUPPORTED;
10301 }
10302
10303 /****************************************************************
10304  _spoolss_AddPortEx
10305 ****************************************************************/
10306
10307 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10308                           struct spoolss_AddPortEx *r)
10309 {
10310         p->rng_fault_state = true;
10311         return WERR_NOT_SUPPORTED;
10312 }
10313
10314 /****************************************************************
10315  _spoolss_RouterFindFirstPrinterChangeNotification
10316 ****************************************************************/
10317
10318 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10319                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10320 {
10321         p->rng_fault_state = true;
10322         return WERR_NOT_SUPPORTED;
10323 }
10324
10325 /****************************************************************
10326  _spoolss_SpoolerInit
10327 ****************************************************************/
10328
10329 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10330                             struct spoolss_SpoolerInit *r)
10331 {
10332         p->rng_fault_state = true;
10333         return WERR_NOT_SUPPORTED;
10334 }
10335
10336 /****************************************************************
10337  _spoolss_ResetPrinterEx
10338 ****************************************************************/
10339
10340 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10341                                struct spoolss_ResetPrinterEx *r)
10342 {
10343         p->rng_fault_state = true;
10344         return WERR_NOT_SUPPORTED;
10345 }
10346
10347 /****************************************************************
10348  _spoolss_RouterReplyPrinterEx
10349 ****************************************************************/
10350
10351 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10352                                      struct spoolss_RouterReplyPrinterEx *r)
10353 {
10354         p->rng_fault_state = true;
10355         return WERR_NOT_SUPPORTED;
10356 }
10357
10358 /****************************************************************
10359  _spoolss_44
10360 ****************************************************************/
10361
10362 WERROR _spoolss_44(struct pipes_struct *p,
10363                    struct spoolss_44 *r)
10364 {
10365         p->rng_fault_state = true;
10366         return WERR_NOT_SUPPORTED;
10367 }
10368
10369 /****************************************************************
10370  _spoolss_SetPort
10371 ****************************************************************/
10372
10373 WERROR _spoolss_SetPort(struct pipes_struct *p,
10374                         struct spoolss_SetPort *r)
10375 {
10376         p->rng_fault_state = true;
10377         return WERR_NOT_SUPPORTED;
10378 }
10379
10380 /****************************************************************
10381  _spoolss_4a
10382 ****************************************************************/
10383
10384 WERROR _spoolss_4a(struct pipes_struct *p,
10385                    struct spoolss_4a *r)
10386 {
10387         p->rng_fault_state = true;
10388         return WERR_NOT_SUPPORTED;
10389 }
10390
10391 /****************************************************************
10392  _spoolss_4b
10393 ****************************************************************/
10394
10395 WERROR _spoolss_4b(struct pipes_struct *p,
10396                    struct spoolss_4b *r)
10397 {
10398         p->rng_fault_state = true;
10399         return WERR_NOT_SUPPORTED;
10400 }
10401
10402 /****************************************************************
10403  _spoolss_4c
10404 ****************************************************************/
10405
10406 WERROR _spoolss_4c(struct pipes_struct *p,
10407                    struct spoolss_4c *r)
10408 {
10409         p->rng_fault_state = true;
10410         return WERR_NOT_SUPPORTED;
10411 }
10412
10413 /****************************************************************
10414  _spoolss_53
10415 ****************************************************************/
10416
10417 WERROR _spoolss_53(struct pipes_struct *p,
10418                    struct spoolss_53 *r)
10419 {
10420         p->rng_fault_state = true;
10421         return WERR_NOT_SUPPORTED;
10422 }
10423
10424 /****************************************************************
10425  _spoolss_AddPerMachineConnection
10426 ****************************************************************/
10427
10428 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10429                                         struct spoolss_AddPerMachineConnection *r)
10430 {
10431         p->rng_fault_state = true;
10432         return WERR_NOT_SUPPORTED;
10433 }
10434
10435 /****************************************************************
10436  _spoolss_DeletePerMachineConnection
10437 ****************************************************************/
10438
10439 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10440                                            struct spoolss_DeletePerMachineConnection *r)
10441 {
10442         p->rng_fault_state = true;
10443         return WERR_NOT_SUPPORTED;
10444 }
10445
10446 /****************************************************************
10447  _spoolss_EnumPerMachineConnections
10448 ****************************************************************/
10449
10450 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10451                                           struct spoolss_EnumPerMachineConnections *r)
10452 {
10453         p->rng_fault_state = true;
10454         return WERR_NOT_SUPPORTED;
10455 }
10456
10457 /****************************************************************
10458  _spoolss_5a
10459 ****************************************************************/
10460
10461 WERROR _spoolss_5a(struct pipes_struct *p,
10462                    struct spoolss_5a *r)
10463 {
10464         p->rng_fault_state = true;
10465         return WERR_NOT_SUPPORTED;
10466 }
10467
10468 /****************************************************************
10469  _spoolss_5b
10470 ****************************************************************/
10471
10472 WERROR _spoolss_5b(struct pipes_struct *p,
10473                    struct spoolss_5b *r)
10474 {
10475         p->rng_fault_state = true;
10476         return WERR_NOT_SUPPORTED;
10477 }
10478
10479 /****************************************************************
10480  _spoolss_5c
10481 ****************************************************************/
10482
10483 WERROR _spoolss_5c(struct pipes_struct *p,
10484                    struct spoolss_5c *r)
10485 {
10486         p->rng_fault_state = true;
10487         return WERR_NOT_SUPPORTED;
10488 }
10489
10490 /****************************************************************
10491  _spoolss_5d
10492 ****************************************************************/
10493
10494 WERROR _spoolss_5d(struct pipes_struct *p,
10495                    struct spoolss_5d *r)
10496 {
10497         p->rng_fault_state = true;
10498         return WERR_NOT_SUPPORTED;
10499 }
10500
10501 /****************************************************************
10502  _spoolss_5e
10503 ****************************************************************/
10504
10505 WERROR _spoolss_5e(struct pipes_struct *p,
10506                    struct spoolss_5e *r)
10507 {
10508         p->rng_fault_state = true;
10509         return WERR_NOT_SUPPORTED;
10510 }
10511
10512 /****************************************************************
10513  _spoolss_5f
10514 ****************************************************************/
10515
10516 WERROR _spoolss_5f(struct pipes_struct *p,
10517                    struct spoolss_5f *r)
10518 {
10519         p->rng_fault_state = true;
10520         return WERR_NOT_SUPPORTED;
10521 }
10522
10523 /****************************************************************
10524  _spoolss_60
10525 ****************************************************************/
10526
10527 WERROR _spoolss_60(struct pipes_struct *p,
10528                    struct spoolss_60 *r)
10529 {
10530         p->rng_fault_state = true;
10531         return WERR_NOT_SUPPORTED;
10532 }
10533
10534 /****************************************************************
10535  _spoolss_61
10536 ****************************************************************/
10537
10538 WERROR _spoolss_61(struct pipes_struct *p,
10539                    struct spoolss_61 *r)
10540 {
10541         p->rng_fault_state = true;
10542         return WERR_NOT_SUPPORTED;
10543 }
10544
10545 /****************************************************************
10546  _spoolss_62
10547 ****************************************************************/
10548
10549 WERROR _spoolss_62(struct pipes_struct *p,
10550                    struct spoolss_62 *r)
10551 {
10552         p->rng_fault_state = true;
10553         return WERR_NOT_SUPPORTED;
10554 }
10555
10556 /****************************************************************
10557  _spoolss_63
10558 ****************************************************************/
10559
10560 WERROR _spoolss_63(struct pipes_struct *p,
10561                    struct spoolss_63 *r)
10562 {
10563         p->rng_fault_state = true;
10564         return WERR_NOT_SUPPORTED;
10565 }
10566
10567 /****************************************************************
10568  _spoolss_64
10569 ****************************************************************/
10570
10571 WERROR _spoolss_64(struct pipes_struct *p,
10572                    struct spoolss_64 *r)
10573 {
10574         p->rng_fault_state = true;
10575         return WERR_NOT_SUPPORTED;
10576 }
10577
10578 /****************************************************************
10579  _spoolss_65
10580 ****************************************************************/
10581
10582 WERROR _spoolss_65(struct pipes_struct *p,
10583                    struct spoolss_65 *r)
10584 {
10585         p->rng_fault_state = true;
10586         return WERR_NOT_SUPPORTED;
10587 }
10588
10589 /****************************************************************
10590  _spoolss_GetCorePrinterDrivers
10591 ****************************************************************/
10592
10593 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10594                                       struct spoolss_GetCorePrinterDrivers *r)
10595 {
10596         p->rng_fault_state = true;
10597         return WERR_NOT_SUPPORTED;
10598 }
10599
10600 /****************************************************************
10601  _spoolss_67
10602 ****************************************************************/
10603
10604 WERROR _spoolss_67(struct pipes_struct *p,
10605                    struct spoolss_67 *r)
10606 {
10607         p->rng_fault_state = true;
10608         return WERR_NOT_SUPPORTED;
10609 }
10610
10611 /****************************************************************
10612  _spoolss_GetPrinterDriverPackagePath
10613 ****************************************************************/
10614
10615 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10616                                             struct spoolss_GetPrinterDriverPackagePath *r)
10617 {
10618         p->rng_fault_state = true;
10619         return WERR_NOT_SUPPORTED;
10620 }
10621
10622 /****************************************************************
10623  _spoolss_69
10624 ****************************************************************/
10625
10626 WERROR _spoolss_69(struct pipes_struct *p,
10627                    struct spoolss_69 *r)
10628 {
10629         p->rng_fault_state = true;
10630         return WERR_NOT_SUPPORTED;
10631 }
10632
10633 /****************************************************************
10634  _spoolss_6a
10635 ****************************************************************/
10636
10637 WERROR _spoolss_6a(struct pipes_struct *p,
10638                    struct spoolss_6a *r)
10639 {
10640         p->rng_fault_state = true;
10641         return WERR_NOT_SUPPORTED;
10642 }
10643
10644 /****************************************************************
10645  _spoolss_6b
10646 ****************************************************************/
10647
10648 WERROR _spoolss_6b(struct pipes_struct *p,
10649                    struct spoolss_6b *r)
10650 {
10651         p->rng_fault_state = true;
10652         return WERR_NOT_SUPPORTED;
10653 }
10654
10655 /****************************************************************
10656  _spoolss_6c
10657 ****************************************************************/
10658
10659 WERROR _spoolss_6c(struct pipes_struct *p,
10660                    struct spoolss_6c *r)
10661 {
10662         p->rng_fault_state = true;
10663         return WERR_NOT_SUPPORTED;
10664 }
10665
10666 /****************************************************************
10667  _spoolss_6d
10668 ****************************************************************/
10669
10670 WERROR _spoolss_6d(struct pipes_struct *p,
10671                    struct spoolss_6d *r)
10672 {
10673         p->rng_fault_state = true;
10674         return WERR_NOT_SUPPORTED;
10675 }