s3-messages: only include messages.h where needed.
[vlendec/samba-autobuild/.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 "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "rpc_client/cli_pipe.h"
37 #include "librpc/gen_ndr/messaging.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
53 /* macros stolen from s4 spoolss server */
54 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
55         ((info)?ndr_size_##fn(info, level, 0):0)
56
57 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
58         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
59
60 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
61         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
62
63 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
64
65 #undef DBGC_CLASS
66 #define DBGC_CLASS DBGC_RPC_SRV
67
68 #ifndef MAX_OPEN_PRINTER_EXS
69 #define MAX_OPEN_PRINTER_EXS 50
70 #endif
71
72 struct notify_back_channel;
73
74 /* structure to store the printer handles */
75 /* and a reference to what it's pointing to */
76 /* and the notify info asked about */
77 /* that's the central struct */
78 struct printer_handle {
79         struct printer_handle *prev, *next;
80         bool document_started;
81         bool page_started;
82         uint32 jobid; /* jobid in printing backend */
83         int printer_type;
84         const char *servername;
85         fstring sharename;
86         uint32 type;
87         uint32 access_granted;
88         struct {
89                 uint32 flags;
90                 uint32 options;
91                 fstring localmachine;
92                 uint32 printerlocal;
93                 struct spoolss_NotifyOption *option;
94                 struct policy_handle cli_hnd;
95                 struct notify_back_channel *cli_chan;
96                 uint32 change;
97                 /* are we in a FindNextPrinterChangeNotify() call? */
98                 bool fnpcn;
99                 struct messaging_context *msg_ctx;
100         } notify;
101         struct {
102                 fstring machine;
103                 fstring user;
104         } client;
105
106         /* devmode sent in the OpenPrinter() call */
107         struct spoolss_DeviceMode *devmode;
108
109         /* TODO cache the printer info2 structure */
110         struct spoolss_PrinterInfo2 *info2;
111
112 };
113
114 static struct printer_handle *printers_list;
115
116 struct printer_session_counter {
117         struct printer_session_counter *next;
118         struct printer_session_counter *prev;
119
120         int snum;
121         uint32_t counter;
122 };
123
124 static struct printer_session_counter *counter_list;
125
126 struct notify_back_channel {
127         struct notify_back_channel *prev, *next;
128
129         /* associated client */
130         struct sockaddr_storage client_address;
131
132         /* print notify back-channel pipe handle*/
133         struct rpc_pipe_client *cli_pipe;
134         struct dcerpc_binding_handle *binding_handle;
135         uint32_t active_connections;
136 };
137
138 static struct notify_back_channel *back_channels;
139
140 /* Map generic permissions to printer object specific permissions */
141
142 const struct standard_mapping printer_std_mapping = {
143         PRINTER_READ,
144         PRINTER_WRITE,
145         PRINTER_EXECUTE,
146         PRINTER_ALL_ACCESS
147 };
148
149 /* Map generic permissions to print server object specific permissions */
150
151 const struct standard_mapping printserver_std_mapping = {
152         SERVER_READ,
153         SERVER_WRITE,
154         SERVER_EXECUTE,
155         SERVER_ALL_ACCESS
156 };
157
158 /* API table for Xcv Monitor functions */
159
160 struct xcv_api_table {
161         const char *name;
162         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
163 };
164
165 static void prune_printername_cache(void);
166
167 /********************************************************************
168  * Canonicalize servername.
169  ********************************************************************/
170
171 static const char *canon_servername(const char *servername)
172 {
173         const char *pservername = servername;
174         while (*pservername == '\\') {
175                 pservername++;
176         }
177         return pservername;
178 }
179
180 /* translate between internal status numbers and NT status numbers */
181 static int nt_printj_status(int v)
182 {
183         switch (v) {
184         case LPQ_QUEUED:
185                 return 0;
186         case LPQ_PAUSED:
187                 return JOB_STATUS_PAUSED;
188         case LPQ_SPOOLING:
189                 return JOB_STATUS_SPOOLING;
190         case LPQ_PRINTING:
191                 return JOB_STATUS_PRINTING;
192         case LPQ_ERROR:
193                 return JOB_STATUS_ERROR;
194         case LPQ_DELETING:
195                 return JOB_STATUS_DELETING;
196         case LPQ_OFFLINE:
197                 return JOB_STATUS_OFFLINE;
198         case LPQ_PAPEROUT:
199                 return JOB_STATUS_PAPEROUT;
200         case LPQ_PRINTED:
201                 return JOB_STATUS_PRINTED;
202         case LPQ_DELETED:
203                 return JOB_STATUS_DELETED;
204         case LPQ_BLOCKED:
205                 return JOB_STATUS_BLOCKED_DEVQ;
206         case LPQ_USER_INTERVENTION:
207                 return JOB_STATUS_USER_INTERVENTION;
208         }
209         return 0;
210 }
211
212 static int nt_printq_status(int v)
213 {
214         switch (v) {
215         case LPQ_PAUSED:
216                 return PRINTER_STATUS_PAUSED;
217         case LPQ_QUEUED:
218         case LPQ_SPOOLING:
219         case LPQ_PRINTING:
220                 return 0;
221         }
222         return 0;
223 }
224
225 /***************************************************************************
226  Disconnect from the client
227 ****************************************************************************/
228
229 static void srv_spoolss_replycloseprinter(int snum,
230                                           struct printer_handle *prn_hnd)
231 {
232         WERROR result;
233         NTSTATUS status;
234
235         /*
236          * Tell the specific printing tdb we no longer want messages for this printer
237          * by deregistering our PID.
238          */
239
240         if (!print_notify_deregister_pid(snum)) {
241                 DEBUG(0, ("Failed to register our pid for printer %s\n",
242                           lp_const_servicename(snum)));
243         }
244
245         /* weird if the test succeeds !!! */
246         if (prn_hnd->notify.cli_chan == NULL ||
247             prn_hnd->notify.cli_chan->active_connections == 0) {
248                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
249                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
250                 TALLOC_FREE(prn_hnd->notify.cli_chan);
251                 return;
252         }
253
254         status = dcerpc_spoolss_ReplyClosePrinter(
255                                         prn_hnd->notify.cli_chan->binding_handle,
256                                         talloc_tos(),
257                                         &prn_hnd->notify.cli_hnd,
258                                         &result);
259         if (!NT_STATUS_IS_OK(status)) {
260                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
261                           nt_errstr(status)));
262                 result = ntstatus_to_werror(status);
263         } else if (!W_ERROR_IS_OK(result)) {
264                 DEBUG(0, ("reply_close_printer failed [%s].\n",
265                           win_errstr(result)));
266         }
267
268         /* if it's the last connection, deconnect the IPC$ share */
269         if (prn_hnd->notify.cli_chan->active_connections == 1) {
270
271                 prn_hnd->notify.cli_chan->binding_handle = NULL;
272                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
273                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
274                 TALLOC_FREE(prn_hnd->notify.cli_chan);
275
276                 if (prn_hnd->notify.msg_ctx != NULL) {
277                         messaging_deregister(prn_hnd->notify.msg_ctx,
278                                              MSG_PRINTER_NOTIFY2, NULL);
279
280                         /*
281                          * Tell the serverid.tdb we're no longer
282                          * interested in printer notify messages.
283                          */
284
285                         serverid_register_msg_flags(
286                                 messaging_server_id(prn_hnd->notify.msg_ctx),
287                                 false, FLAG_MSG_PRINT_NOTIFY);
288                 }
289         }
290
291         if (prn_hnd->notify.cli_chan) {
292                 prn_hnd->notify.cli_chan->active_connections--;
293         }
294 }
295
296 /****************************************************************************
297  Functions to free a printer entry datastruct.
298 ****************************************************************************/
299
300 static int printer_entry_destructor(struct printer_handle *Printer)
301 {
302         if (Printer->notify.cli_chan != NULL &&
303             Printer->notify.cli_chan->active_connections > 0) {
304                 int snum = -1;
305
306                 switch(Printer->printer_type) {
307                 case SPLHND_SERVER:
308                         srv_spoolss_replycloseprinter(snum, Printer);
309                         break;
310
311                 case SPLHND_PRINTER:
312                         snum = print_queue_snum(Printer->sharename);
313                         if (snum != -1) {
314                                 srv_spoolss_replycloseprinter(snum, Printer);
315                         }
316                         break;
317                 default:
318                         break;
319                 }
320         }
321
322         Printer->notify.flags=0;
323         Printer->notify.options=0;
324         Printer->notify.localmachine[0]='\0';
325         Printer->notify.printerlocal=0;
326         TALLOC_FREE(Printer->notify.option);
327         TALLOC_FREE(Printer->devmode);
328
329         /* Remove from the internal list. */
330         DLIST_REMOVE(printers_list, Printer);
331         return 0;
332 }
333
334 /****************************************************************************
335   find printer index by handle
336 ****************************************************************************/
337
338 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
339                                                         struct policy_handle *hnd)
340 {
341         struct printer_handle *find_printer = NULL;
342
343         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
344                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
345                 return NULL;
346         }
347
348         return find_printer;
349 }
350
351 /****************************************************************************
352  Close printer index by handle.
353 ****************************************************************************/
354
355 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
356 {
357         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
358
359         if (!Printer) {
360                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
361                         OUR_HANDLE(hnd)));
362                 return false;
363         }
364
365         close_policy_hnd(p, hnd);
366
367         return true;
368 }
369
370 /****************************************************************************
371  Delete a printer given a handle.
372 ****************************************************************************/
373
374 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
375                                   const char *sharename,
376                                   struct messaging_context *msg_ctx)
377 {
378         char *cmd = lp_deleteprinter_cmd();
379         char *command = NULL;
380         int ret;
381         bool is_print_op = false;
382
383         /* can't fail if we don't try */
384
385         if ( !*cmd )
386                 return WERR_OK;
387
388         command = talloc_asprintf(ctx,
389                         "%s \"%s\"",
390                         cmd, sharename);
391         if (!command) {
392                 return WERR_NOMEM;
393         }
394         if ( token )
395                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
396
397         DEBUG(10,("Running [%s]\n", command));
398
399         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
400
401         if ( is_print_op )
402                 become_root();
403
404         if ( (ret = smbrun(command, NULL)) == 0 ) {
405                 /* Tell everyone we updated smb.conf. */
406                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
407         }
408
409         if ( is_print_op )
410                 unbecome_root();
411
412         /********** END SePrintOperatorPrivlege BLOCK **********/
413
414         DEBUGADD(10,("returned [%d]\n", ret));
415
416         TALLOC_FREE(command);
417
418         if (ret != 0)
419                 return WERR_BADFID; /* What to return here? */
420
421         /* go ahead and re-read the services immediately */
422         become_root();
423         reload_services(msg_ctx, -1, false);
424         unbecome_root();
425
426         if ( lp_servicenumber( sharename ) >= 0 )
427                 return WERR_ACCESS_DENIED;
428
429         return WERR_OK;
430 }
431
432 /****************************************************************************
433  Delete a printer given a handle.
434 ****************************************************************************/
435
436 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
437 {
438         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
439         WERROR result;
440
441         if (!Printer) {
442                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
443                         OUR_HANDLE(hnd)));
444                 return WERR_BADFID;
445         }
446
447         /*
448          * It turns out that Windows allows delete printer on a handle
449          * opened by an admin user, then used on a pipe handle created
450          * by an anonymous user..... but they're working on security.... riiight !
451          * JRA.
452          */
453
454         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
455                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
456                 return WERR_ACCESS_DENIED;
457         }
458
459         /* this does not need a become root since the access check has been
460            done on the handle already */
461
462         result = winreg_delete_printer_key(p->mem_ctx,
463                                            get_session_info_system(),
464                                            p->msg_ctx,
465                                            Printer->sharename,
466                                            "");
467         if (!W_ERROR_IS_OK(result)) {
468                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
469                 return WERR_BADFID;
470         }
471
472         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
473                                      Printer->sharename, p->msg_ctx);
474         if (!W_ERROR_IS_OK(result)) {
475                 return result;
476         }
477         prune_printername_cache();
478         return WERR_OK;
479 }
480
481 /****************************************************************************
482  Return the snum of a printer corresponding to an handle.
483 ****************************************************************************/
484
485 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
486                              int *number, struct share_params **params)
487 {
488         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
489
490         if (!Printer) {
491                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
492                         OUR_HANDLE(hnd)));
493                 return false;
494         }
495
496         switch (Printer->printer_type) {
497                 case SPLHND_PRINTER:
498                         DEBUG(4,("short name:%s\n", Printer->sharename));
499                         *number = print_queue_snum(Printer->sharename);
500                         return (*number != -1);
501                 case SPLHND_SERVER:
502                         return false;
503                 default:
504                         return false;
505         }
506 }
507
508 /****************************************************************************
509  Set printer handle type.
510  Check if it's \\server or \\server\printer
511 ****************************************************************************/
512
513 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
514 {
515         DEBUG(3,("Setting printer type=%s\n", handlename));
516
517         /* it's a print server */
518         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
519                 DEBUGADD(4,("Printer is a print server\n"));
520                 Printer->printer_type = SPLHND_SERVER;
521         }
522         /* it's a printer (set_printer_hnd_name() will handle port monitors */
523         else {
524                 DEBUGADD(4,("Printer is a printer\n"));
525                 Printer->printer_type = SPLHND_PRINTER;
526         }
527
528         return true;
529 }
530
531 static void prune_printername_cache_fn(const char *key, const char *value,
532                                        time_t timeout, void *private_data)
533 {
534         gencache_del(key);
535 }
536
537 static void prune_printername_cache(void)
538 {
539         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
540 }
541
542 /****************************************************************************
543  Set printer handle name..  Accept names like \\server, \\server\printer,
544  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
545  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
546  XcvDataPort() interface.
547 ****************************************************************************/
548
549 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
550                                    const struct auth_serversupplied_info *session_info,
551                                    struct messaging_context *msg_ctx,
552                                    struct printer_handle *Printer,
553                                    const char *handlename)
554 {
555         int snum;
556         int n_services=lp_numservices();
557         char *aprinter;
558         const char *printername;
559         const char *servername = NULL;
560         fstring sname;
561         bool found = false;
562         struct spoolss_PrinterInfo2 *info2 = NULL;
563         WERROR result;
564         char *p;
565
566         /*
567          * Hopefully nobody names his printers like this. Maybe \ or ,
568          * are illegal in printer names even?
569          */
570         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
571         char *cache_key;
572         char *tmp;
573
574         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
575                 (unsigned long)strlen(handlename)));
576
577         aprinter = CONST_DISCARD(char *, handlename);
578         if ( *handlename == '\\' ) {
579                 servername = canon_servername(handlename);
580                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
581                         *aprinter = '\0';
582                         aprinter++;
583                 }
584                 if (!is_myname_or_ipaddr(servername)) {
585                         return WERR_INVALID_PRINTER_NAME;
586                 }
587                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
588                 if (Printer->servername == NULL) {
589                         return WERR_NOMEM;
590                 }
591         }
592
593         if (Printer->printer_type == SPLHND_SERVER) {
594                 return WERR_OK;
595         }
596
597         if (Printer->printer_type != SPLHND_PRINTER) {
598                 return WERR_INVALID_HANDLE;
599         }
600
601         DEBUGADD(5, ("searching for [%s]\n", aprinter));
602
603         p = strchr(aprinter, ',');
604         if (p != NULL) {
605                 char *p2 = p;
606                 p++;
607                 if (*p == ' ') {
608                         p++;
609                 }
610                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
611                         *p2 = '\0';
612                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
613                         *p2 = '\0';
614                 }
615         }
616
617         if (p) {
618                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
619         }
620
621         /* check for the Port Monitor Interface */
622         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
623                 Printer->printer_type = SPLHND_PORTMON_TCP;
624                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
625                 found = true;
626         }
627         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
628                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
629                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
630                 found = true;
631         }
632
633         /*
634          * With hundreds of printers, the "for" loop iterating all
635          * shares can be quite expensive, as it is done on every
636          * OpenPrinter. The loop maps "aprinter" to "sname", the
637          * result of which we cache in gencache.
638          */
639
640         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
641                                     aprinter);
642         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
643
644                 found = (strcmp(tmp, printer_not_found) != 0);
645                 if (!found) {
646                         DEBUG(4, ("Printer %s not found\n", aprinter));
647                         SAFE_FREE(tmp);
648                         return WERR_INVALID_PRINTER_NAME;
649                 }
650                 fstrcpy(sname, tmp);
651                 SAFE_FREE(tmp);
652         }
653
654         /* Search all sharenames first as this is easier than pulling
655            the printer_info_2 off of disk. Don't use find_service() since
656            that calls out to map_username() */
657
658         /* do another loop to look for printernames */
659         for (snum = 0; !found && snum < n_services; snum++) {
660                 const char *printer = lp_const_servicename(snum);
661
662                 /* no point going on if this is not a printer */
663                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
664                         continue;
665                 }
666
667                 /* ignore [printers] share */
668                 if (strequal(printer, "printers")) {
669                         continue;
670                 }
671
672                 fstrcpy(sname, printer);
673                 if (strequal(aprinter, printer)) {
674                         found = true;
675                         break;
676                 }
677
678                 /* no point looking up the printer object if
679                    we aren't allowing printername != sharename */
680                 if (lp_force_printername(snum)) {
681                         continue;
682                 }
683
684                 result = winreg_get_printer(mem_ctx,
685                                             session_info,
686                                             msg_ctx,
687                                             sname,
688                                             &info2);
689                 if ( !W_ERROR_IS_OK(result) ) {
690                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
691                                  sname, win_errstr(result)));
692                         continue;
693                 }
694
695                 printername = strrchr(info2->printername, '\\');
696                 if (printername == NULL) {
697                         printername = info2->printername;
698                 } else {
699                         printername++;
700                 }
701
702                 if (strequal(printername, aprinter)) {
703                         found = true;
704                         break;
705                 }
706
707                 DEBUGADD(10, ("printername: %s\n", printername));
708
709                 TALLOC_FREE(info2);
710         }
711
712         if ( !found ) {
713                 if (cache_key != NULL) {
714                         gencache_set(cache_key, printer_not_found,
715                                      time(NULL)+300);
716                         TALLOC_FREE(cache_key);
717                 }
718                 DEBUGADD(4,("Printer not found\n"));
719                 return WERR_INVALID_PRINTER_NAME;
720         }
721
722         if (cache_key != NULL) {
723                 gencache_set(cache_key, sname, time(NULL)+300);
724                 TALLOC_FREE(cache_key);
725         }
726
727         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
728
729         fstrcpy(Printer->sharename, sname);
730
731         return WERR_OK;
732 }
733
734 /****************************************************************************
735  Find first available printer slot. creates a printer handle for you.
736  ****************************************************************************/
737
738 static WERROR open_printer_hnd(struct pipes_struct *p,
739                                struct policy_handle *hnd,
740                                const char *name,
741                                uint32_t access_granted)
742 {
743         struct printer_handle *new_printer;
744         WERROR result;
745
746         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
747
748         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
749         if (new_printer == NULL) {
750                 return WERR_NOMEM;
751         }
752         talloc_set_destructor(new_printer, printer_entry_destructor);
753
754         /* This also steals the printer_handle on the policy_handle */
755         if (!create_policy_hnd(p, hnd, new_printer)) {
756                 TALLOC_FREE(new_printer);
757                 return WERR_INVALID_HANDLE;
758         }
759
760         /* Add to the internal list. */
761         DLIST_ADD(printers_list, new_printer);
762
763         new_printer->notify.option=NULL;
764
765         if (!set_printer_hnd_printertype(new_printer, name)) {
766                 close_printer_handle(p, hnd);
767                 return WERR_INVALID_HANDLE;
768         }
769
770         result = set_printer_hnd_name(p->mem_ctx,
771                                       get_session_info_system(),
772                                       p->msg_ctx,
773                                       new_printer, name);
774         if (!W_ERROR_IS_OK(result)) {
775                 close_printer_handle(p, hnd);
776                 return result;
777         }
778
779         new_printer->access_granted = access_granted;
780
781         DEBUG(5, ("%d printer handles active\n",
782                   (int)num_pipe_handles(p)));
783
784         return WERR_OK;
785 }
786
787 /***************************************************************************
788  check to see if the client motify handle is monitoring the notification
789  given by (notify_type, notify_field).
790  **************************************************************************/
791
792 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
793                                       uint16_t notify_field)
794 {
795         return true;
796 }
797
798 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
799                                 uint16_t notify_field)
800 {
801         struct spoolss_NotifyOption *option = p->notify.option;
802         uint32_t i, j;
803
804         /*
805          * Flags should always be zero when the change notify
806          * is registered by the client's spooler.  A user Win32 app
807          * might use the flags though instead of the NOTIFY_OPTION_INFO
808          * --jerry
809          */
810
811         if (!option) {
812                 return false;
813         }
814
815         if (p->notify.flags)
816                 return is_monitoring_event_flags(
817                         p->notify.flags, notify_type, notify_field);
818
819         for (i = 0; i < option->count; i++) {
820
821                 /* Check match for notify_type */
822
823                 if (option->types[i].type != notify_type)
824                         continue;
825
826                 /* Check match for field */
827
828                 for (j = 0; j < option->types[i].count; j++) {
829                         if (option->types[i].fields[j].field == notify_field) {
830                                 return true;
831                         }
832                 }
833         }
834
835         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
836                    p->servername, p->sharename, notify_type, notify_field));
837
838         return false;
839 }
840
841 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
842         _data->data.integer[0] = _integer; \
843         _data->data.integer[1] = 0;
844
845
846 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
847         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
848         if (!_data->data.string.string) {\
849                 _data->data.string.size = 0; \
850         } \
851         _data->data.string.size = strlen_m_term(_p) * 2;
852
853 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
854         _data->data.devmode.devmode = _devmode;
855
856 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
857         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
858         if (!_data->data.sd.sd) { \
859                 _data->data.sd.sd_size = 0; \
860         } \
861         _data->data.sd.sd_size = \
862                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
863
864 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
865                                    struct tm *t,
866                                    const char **pp,
867                                    uint32_t *plen)
868 {
869         struct spoolss_Time st;
870         uint32_t len = 16;
871         char *p;
872
873         if (!init_systemtime(&st, t)) {
874                 return;
875         }
876
877         p = talloc_array(mem_ctx, char, len);
878         if (!p) {
879                 return;
880         }
881
882         /*
883          * Systemtime must be linearized as a set of UINT16's.
884          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
885          */
886
887         SSVAL(p, 0, st.year);
888         SSVAL(p, 2, st.month);
889         SSVAL(p, 4, st.day_of_week);
890         SSVAL(p, 6, st.day);
891         SSVAL(p, 8, st.hour);
892         SSVAL(p, 10, st.minute);
893         SSVAL(p, 12, st.second);
894         SSVAL(p, 14, st.millisecond);
895
896         *pp = p;
897         *plen = len;
898 }
899
900 /* Convert a notification message to a struct spoolss_Notify */
901
902 static void notify_one_value(struct spoolss_notify_msg *msg,
903                              struct spoolss_Notify *data,
904                              TALLOC_CTX *mem_ctx)
905 {
906         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
907 }
908
909 static void notify_string(struct spoolss_notify_msg *msg,
910                           struct spoolss_Notify *data,
911                           TALLOC_CTX *mem_ctx)
912 {
913         /* The length of the message includes the trailing \0 */
914
915         data->data.string.size = msg->len * 2;
916         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
917         if (!data->data.string.string) {
918                 data->data.string.size = 0;
919                 return;
920         }
921 }
922
923 static void notify_system_time(struct spoolss_notify_msg *msg,
924                                struct spoolss_Notify *data,
925                                TALLOC_CTX *mem_ctx)
926 {
927         data->data.string.string = NULL;
928         data->data.string.size = 0;
929
930         if (msg->len != sizeof(time_t)) {
931                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
932                           msg->len));
933                 return;
934         }
935
936         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
937                                &data->data.string.string,
938                                &data->data.string.size);
939 }
940
941 struct notify2_message_table {
942         const char *name;
943         void (*fn)(struct spoolss_notify_msg *msg,
944                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
945 };
946
947 static struct notify2_message_table printer_notify_table[] = {
948         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
949         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
950         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
951         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
952         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
953         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
954         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
955         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
956         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
957         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
958         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
959         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
960         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
961         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
962         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
963         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
964         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
965         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
966         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
967 };
968
969 static struct notify2_message_table job_notify_table[] = {
970         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
971         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
972         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
973         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
974         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
975         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
976         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
977         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
978         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
979         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
980         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
981         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
982         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
983         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
984         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
985         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
986         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
987         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
988         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
989         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
990         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
991         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
992         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
993         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
994 };
995
996
997 /***********************************************************************
998  Allocate talloc context for container object
999  **********************************************************************/
1000
1001 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1002 {
1003         if ( !ctr )
1004                 return;
1005
1006         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1007
1008         return;
1009 }
1010
1011 /***********************************************************************
1012  release all allocated memory and zero out structure
1013  **********************************************************************/
1014
1015 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1016 {
1017         if ( !ctr )
1018                 return;
1019
1020         if ( ctr->ctx )
1021                 talloc_destroy(ctr->ctx);
1022
1023         ZERO_STRUCTP(ctr);
1024
1025         return;
1026 }
1027
1028 /***********************************************************************
1029  **********************************************************************/
1030
1031 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1032 {
1033         if ( !ctr )
1034                 return NULL;
1035
1036         return ctr->ctx;
1037 }
1038
1039 /***********************************************************************
1040  **********************************************************************/
1041
1042 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1043 {
1044         if ( !ctr || !ctr->msg_groups )
1045                 return NULL;
1046
1047         if ( idx >= ctr->num_groups )
1048                 return NULL;
1049
1050         return &ctr->msg_groups[idx];
1051
1052 }
1053
1054 /***********************************************************************
1055  How many groups of change messages do we have ?
1056  **********************************************************************/
1057
1058 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1059 {
1060         if ( !ctr )
1061                 return 0;
1062
1063         return ctr->num_groups;
1064 }
1065
1066 /***********************************************************************
1067  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1068  **********************************************************************/
1069
1070 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1071 {
1072         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1073         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1074         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1075         int                             i, new_slot;
1076
1077         if ( !ctr || !msg )
1078                 return 0;
1079
1080         /* loop over all groups looking for a matching printer name */
1081
1082         for ( i=0; i<ctr->num_groups; i++ ) {
1083                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1084                         break;
1085         }
1086
1087         /* add a new group? */
1088
1089         if ( i == ctr->num_groups ) {
1090                 ctr->num_groups++;
1091
1092                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1093                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1094                         return 0;
1095                 }
1096                 ctr->msg_groups = groups;
1097
1098                 /* clear the new entry and set the printer name */
1099
1100                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1101                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1102         }
1103
1104         /* add the change messages; 'i' is the correct index now regardless */
1105
1106         msg_grp = &ctr->msg_groups[i];
1107
1108         msg_grp->num_msgs++;
1109
1110         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1111                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1112                 return 0;
1113         }
1114         msg_grp->msgs = msg_list;
1115
1116         new_slot = msg_grp->num_msgs-1;
1117         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1118
1119         /* need to allocate own copy of data */
1120
1121         if ( msg->len != 0 )
1122                 msg_grp->msgs[new_slot].notify.data = (char *)
1123                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1124
1125         return ctr->num_groups;
1126 }
1127
1128 static void construct_info_data(struct spoolss_Notify *info_data,
1129                                 enum spoolss_NotifyType type,
1130                                 uint16_t field, int id);
1131
1132 /***********************************************************************
1133  Send a change notication message on all handles which have a call
1134  back registered
1135  **********************************************************************/
1136
1137 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1138                                   struct printer_handle *prn_hnd,
1139                                   SPOOLSS_NOTIFY_MSG *messages,
1140                                   uint32_t num_msgs,
1141                                   struct spoolss_Notify **_notifies,
1142                                   int *_count)
1143 {
1144         struct spoolss_Notify *notifies;
1145         SPOOLSS_NOTIFY_MSG *msg;
1146         int count = 0;
1147         uint32_t id;
1148         int i;
1149
1150         notifies = talloc_zero_array(mem_ctx,
1151                                      struct spoolss_Notify, num_msgs);
1152         if (!notifies) {
1153                 return ENOMEM;
1154         }
1155
1156         for (i = 0; i < num_msgs; i++) {
1157
1158                 msg = &messages[i];
1159
1160                 /* Are we monitoring this event? */
1161
1162                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1163                         continue;
1164                 }
1165
1166                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1167                            "for printer [%s]\n",
1168                            msg->type, msg->field, prn_hnd->sharename));
1169
1170                 /*
1171                  * if the is a printer notification handle and not a job
1172                  * notification type, then set the id to 0.
1173                  * Otherwise just use what was specified in the message.
1174                  *
1175                  * When registering change notification on a print server
1176                  * handle we always need to send back the id (snum) matching
1177                  * the printer for which the change took place.
1178                  * For change notify registered on a printer handle,
1179                  * this does not matter and the id should be 0.
1180                  *
1181                  * --jerry
1182                  */
1183
1184                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1185                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1186                         id = 0;
1187                 } else {
1188                         id = msg->id;
1189                 }
1190
1191                 /* Convert unix jobid to smb jobid */
1192
1193                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1194                         id = sysjob_to_jobid(msg->id);
1195
1196                         if (id == -1) {
1197                                 DEBUG(3, ("no such unix jobid %d\n",
1198                                           msg->id));
1199                                 continue;
1200                         }
1201                 }
1202
1203                 construct_info_data(&notifies[count],
1204                                     msg->type, msg->field, id);
1205
1206                 switch(msg->type) {
1207                 case PRINTER_NOTIFY_TYPE:
1208                         if (printer_notify_table[msg->field].fn) {
1209                                 printer_notify_table[msg->field].fn(msg,
1210                                                 &notifies[count], mem_ctx);
1211                         }
1212                         break;
1213
1214                 case JOB_NOTIFY_TYPE:
1215                         if (job_notify_table[msg->field].fn) {
1216                                 job_notify_table[msg->field].fn(msg,
1217                                                 &notifies[count], mem_ctx);
1218                         }
1219                         break;
1220
1221                 default:
1222                         DEBUG(5, ("Unknown notification type %d\n",
1223                                   msg->type));
1224                         continue;
1225                 }
1226
1227                 count++;
1228         }
1229
1230         *_notifies = notifies;
1231         *_count = count;
1232
1233         return 0;
1234 }
1235
1236 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1237                                 struct printer_handle *prn_hnd,
1238                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1239 {
1240         struct spoolss_Notify *notifies;
1241         int count = 0;
1242         union spoolss_ReplyPrinterInfo info;
1243         struct spoolss_NotifyInfo info0;
1244         uint32_t reply_result;
1245         NTSTATUS status;
1246         WERROR werr;
1247         int ret;
1248
1249         /* Is there notification on this handle? */
1250         if (prn_hnd->notify.cli_chan == NULL ||
1251             prn_hnd->notify.cli_chan->active_connections == 0) {
1252                 return 0;
1253         }
1254
1255         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1256                    prn_hnd->servername, prn_hnd->sharename));
1257
1258         /* For this printer? Print servers always receive notifications. */
1259         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1260             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1261                 return 0;
1262         }
1263
1264         DEBUG(10,("Our printer\n"));
1265
1266         /* build the array of change notifications */
1267         ret = build_notify2_messages(mem_ctx, prn_hnd,
1268                                      msg_group->msgs,
1269                                      msg_group->num_msgs,
1270                                      &notifies, &count);
1271         if (ret) {
1272                 return ret;
1273         }
1274
1275         info0.version   = 0x2;
1276         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1277         info0.count     = count;
1278         info0.notifies  = notifies;
1279
1280         info.info0 = &info0;
1281
1282         status = dcerpc_spoolss_RouterReplyPrinterEx(
1283                                 prn_hnd->notify.cli_chan->binding_handle,
1284                                 mem_ctx,
1285                                 &prn_hnd->notify.cli_hnd,
1286                                 prn_hnd->notify.change, /* color */
1287                                 prn_hnd->notify.flags,
1288                                 &reply_result,
1289                                 0, /* reply_type, must be 0 */
1290                                 info, &werr);
1291         if (!NT_STATUS_IS_OK(status)) {
1292                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1293                           "failed: %s\n",
1294                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1295                           nt_errstr(status)));
1296                 werr = ntstatus_to_werror(status);
1297         } else if (!W_ERROR_IS_OK(werr)) {
1298                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1299                           "failed: %s\n",
1300                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1301                           win_errstr(werr)));
1302         }
1303         switch (reply_result) {
1304         case 0:
1305                 break;
1306         case PRINTER_NOTIFY_INFO_DISCARDED:
1307         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1308         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1309                 break;
1310         default:
1311                 break;
1312         }
1313
1314         return 0;
1315 }
1316
1317 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1318 {
1319         struct printer_handle    *p;
1320         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1321         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1322         int ret;
1323
1324         if ( !msg_group ) {
1325                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1326                 return;
1327         }
1328
1329         if (!msg_group->msgs) {
1330                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1331                 return;
1332         }
1333
1334         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1335
1336         /* loop over all printers */
1337
1338         for (p = printers_list; p; p = p->next) {
1339                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1340                 if (ret) {
1341                         goto done;
1342                 }
1343         }
1344
1345 done:
1346         DEBUG(8,("send_notify2_changes: Exit...\n"));
1347         return;
1348 }
1349
1350 /***********************************************************************
1351  **********************************************************************/
1352
1353 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1354 {
1355
1356         uint32_t tv_sec, tv_usec;
1357         size_t offset = 0;
1358
1359         /* Unpack message */
1360
1361         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1362                              msg->printer);
1363
1364         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1365                                 &tv_sec, &tv_usec,
1366                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1367
1368         if (msg->len == 0)
1369                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1370                            &msg->notify.value[0], &msg->notify.value[1]);
1371         else
1372                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1373                            &msg->len, &msg->notify.data);
1374
1375         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1376                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1377
1378         tv->tv_sec = tv_sec;
1379         tv->tv_usec = tv_usec;
1380
1381         if (msg->len == 0)
1382                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1383                           msg->notify.value[1]));
1384         else
1385                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1386
1387         return true;
1388 }
1389
1390 /********************************************************************
1391  Receive a notify2 message list
1392  ********************************************************************/
1393
1394 static void receive_notify2_message_list(struct messaging_context *msg,
1395                                          void *private_data,
1396                                          uint32_t msg_type,
1397                                          struct server_id server_id,
1398                                          DATA_BLOB *data)
1399 {
1400         size_t                  msg_count, i;
1401         char                    *buf = (char *)data->data;
1402         char                    *msg_ptr;
1403         size_t                  msg_len;
1404         SPOOLSS_NOTIFY_MSG      notify;
1405         SPOOLSS_NOTIFY_MSG_CTR  messages;
1406         int                     num_groups;
1407
1408         if (data->length < 4) {
1409                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1410                 return;
1411         }
1412
1413         msg_count = IVAL(buf, 0);
1414         msg_ptr = buf + 4;
1415
1416         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1417
1418         if (msg_count == 0) {
1419                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1420                 return;
1421         }
1422
1423         /* initialize the container */
1424
1425         ZERO_STRUCT( messages );
1426         notify_msg_ctr_init( &messages );
1427
1428         /*
1429          * build message groups for each printer identified
1430          * in a change_notify msg.  Remember that a PCN message
1431          * includes the handle returned for the srv_spoolss_replyopenprinter()
1432          * call.  Therefore messages are grouped according to printer handle.
1433          */
1434
1435         for ( i=0; i<msg_count; i++ ) {
1436                 struct timeval msg_tv;
1437
1438                 if (msg_ptr + 4 - buf > data->length) {
1439                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1440                         return;
1441                 }
1442
1443                 msg_len = IVAL(msg_ptr,0);
1444                 msg_ptr += 4;
1445
1446                 if (msg_ptr + msg_len - buf > data->length) {
1447                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1448                         return;
1449                 }
1450
1451                 /* unpack messages */
1452
1453                 ZERO_STRUCT( notify );
1454                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1455                 msg_ptr += msg_len;
1456
1457                 /* add to correct list in container */
1458
1459                 notify_msg_ctr_addmsg( &messages, &notify );
1460
1461                 /* free memory that might have been allocated by notify2_unpack_msg() */
1462
1463                 if ( notify.len != 0 )
1464                         SAFE_FREE( notify.notify.data );
1465         }
1466
1467         /* process each group of messages */
1468
1469         num_groups = notify_msg_ctr_numgroups( &messages );
1470         for ( i=0; i<num_groups; i++ )
1471                 send_notify2_changes( &messages, i );
1472
1473
1474         /* cleanup */
1475
1476         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1477                 (uint32_t)msg_count ));
1478
1479         notify_msg_ctr_destroy( &messages );
1480
1481         return;
1482 }
1483
1484 /********************************************************************
1485  Send a message to ourself about new driver being installed
1486  so we can upgrade the information for each printer bound to this
1487  driver
1488  ********************************************************************/
1489
1490 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1491                                             struct messaging_context *msg_ctx)
1492 {
1493         int len = strlen(drivername);
1494
1495         if (!len)
1496                 return false;
1497
1498         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1499                 drivername));
1500
1501         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1502                            MSG_PRINTER_DRVUPGRADE,
1503                            (uint8_t *)drivername, len+1);
1504
1505         return true;
1506 }
1507
1508 void srv_spoolss_cleanup(void)
1509 {
1510         struct printer_session_counter *session_counter;
1511
1512         for (session_counter = counter_list;
1513              session_counter != NULL;
1514              session_counter = counter_list) {
1515                 DLIST_REMOVE(counter_list, session_counter);
1516                 TALLOC_FREE(session_counter);
1517         }
1518 }
1519
1520 /**********************************************************************
1521  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1522  over all printers, upgrading ones as necessary
1523  **********************************************************************/
1524
1525 void do_drv_upgrade_printer(struct messaging_context *msg,
1526                             void *private_data,
1527                             uint32_t msg_type,
1528                             struct server_id server_id,
1529                             DATA_BLOB *data)
1530 {
1531         TALLOC_CTX *tmp_ctx;
1532         struct auth_serversupplied_info *session_info = NULL;
1533         struct spoolss_PrinterInfo2 *pinfo2;
1534         NTSTATUS status;
1535         WERROR result;
1536         const char *drivername;
1537         int snum;
1538         int n_services = lp_numservices();
1539
1540         tmp_ctx = talloc_new(NULL);
1541         if (!tmp_ctx) return;
1542
1543         status = make_session_info_system(tmp_ctx, &session_info);
1544         if (!NT_STATUS_IS_OK(status)) {
1545                 DEBUG(0, ("do_drv_upgrade_printer: "
1546                           "Could not create system session_info\n"));
1547                 goto done;
1548         }
1549
1550         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1551         if (!drivername) {
1552                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1553                 goto done;
1554         }
1555
1556         DEBUG(10, ("do_drv_upgrade_printer: "
1557                    "Got message for new driver [%s]\n", drivername));
1558
1559         /* Iterate the printer list */
1560
1561         for (snum = 0; snum < n_services; snum++) {
1562                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1563                         continue;
1564                 }
1565
1566                 /* ignore [printers] share */
1567                 if (strequal(lp_const_servicename(snum), "printers")) {
1568                         continue;
1569                 }
1570
1571                 result = winreg_get_printer(tmp_ctx, session_info, msg,
1572                                             lp_const_servicename(snum),
1573                                             &pinfo2);
1574
1575                 if (!W_ERROR_IS_OK(result)) {
1576                         continue;
1577                 }
1578
1579                 if (!pinfo2->drivername) {
1580                         continue;
1581                 }
1582
1583                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1584                         continue;
1585                 }
1586
1587                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1588
1589                 /* all we care about currently is the change_id */
1590                 result = winreg_printer_update_changeid(tmp_ctx,
1591                                                         session_info,
1592                                                         msg,
1593                                                         pinfo2->printername);
1594
1595                 if (!W_ERROR_IS_OK(result)) {
1596                         DEBUG(3, ("do_drv_upgrade_printer: "
1597                                   "Failed to update changeid [%s]\n",
1598                                   win_errstr(result)));
1599                 }
1600         }
1601
1602         /* all done */
1603 done:
1604         talloc_free(tmp_ctx);
1605 }
1606
1607 /********************************************************************
1608  Update the cache for all printq's with a registered client
1609  connection
1610  ********************************************************************/
1611
1612 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1613 {
1614         struct printer_handle *printer = printers_list;
1615         int snum;
1616
1617         /* loop through all printers and update the cache where
1618            a client is connected */
1619         while (printer) {
1620                 if ((printer->printer_type == SPLHND_PRINTER) &&
1621                     ((printer->notify.cli_chan != NULL) &&
1622                      (printer->notify.cli_chan->active_connections > 0))) {
1623                         snum = print_queue_snum(printer->sharename);
1624                         print_queue_status(msg_ctx, snum, NULL, NULL);
1625                 }
1626
1627                 printer = printer->next;
1628         }
1629
1630         return;
1631 }
1632
1633 /****************************************************************
1634  _spoolss_OpenPrinter
1635 ****************************************************************/
1636
1637 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1638                             struct spoolss_OpenPrinter *r)
1639 {
1640         struct spoolss_OpenPrinterEx e;
1641         WERROR werr;
1642
1643         ZERO_STRUCT(e.in.userlevel);
1644
1645         e.in.printername        = r->in.printername;
1646         e.in.datatype           = r->in.datatype;
1647         e.in.devmode_ctr        = r->in.devmode_ctr;
1648         e.in.access_mask        = r->in.access_mask;
1649         e.in.level              = 0;
1650
1651         e.out.handle            = r->out.handle;
1652
1653         werr = _spoolss_OpenPrinterEx(p, &e);
1654
1655         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1656                 /* OpenPrinterEx returns this for a bad
1657                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1658                  * instead.
1659                  */
1660                 werr = WERR_INVALID_PRINTER_NAME;
1661         }
1662
1663         return werr;
1664 }
1665
1666 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1667                               struct spoolss_DeviceMode *orig,
1668                               struct spoolss_DeviceMode **dest)
1669 {
1670         struct spoolss_DeviceMode *dm;
1671
1672         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1673         if (!dm) {
1674                 return WERR_NOMEM;
1675         }
1676
1677         /* copy all values, then duplicate strings and structs */
1678         *dm = *orig;
1679
1680         dm->devicename = talloc_strdup(dm, orig->devicename);
1681         if (!dm->devicename) {
1682                 return WERR_NOMEM;
1683         }
1684         dm->formname = talloc_strdup(dm, orig->formname);
1685         if (!dm->formname) {
1686                 return WERR_NOMEM;
1687         }
1688         if (orig->driverextra_data.data) {
1689                 dm->driverextra_data.data =
1690                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1691                                         orig->driverextra_data.length);
1692                 if (!dm->driverextra_data.data) {
1693                         return WERR_NOMEM;
1694                 }
1695         }
1696
1697         *dest = dm;
1698         return WERR_OK;
1699 }
1700
1701 /****************************************************************
1702  _spoolss_OpenPrinterEx
1703 ****************************************************************/
1704
1705 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1706                               struct spoolss_OpenPrinterEx *r)
1707 {
1708         int snum;
1709         struct printer_handle *Printer=NULL;
1710         WERROR result;
1711
1712         if (!r->in.printername) {
1713                 return WERR_INVALID_PARAM;
1714         }
1715
1716         if (r->in.level > 3) {
1717                 return WERR_INVALID_PARAM;
1718         }
1719         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1720             (r->in.level == 2 && !r->in.userlevel.level2) ||
1721             (r->in.level == 3 && !r->in.userlevel.level3)) {
1722                 return WERR_INVALID_PARAM;
1723         }
1724
1725         /* some sanity check because you can open a printer or a print server */
1726         /* aka: \\server\printer or \\server */
1727
1728         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1729
1730         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1731         if (!W_ERROR_IS_OK(result)) {
1732                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1733                         "for printer %s\n", r->in.printername));
1734                 ZERO_STRUCTP(r->out.handle);
1735                 return result;
1736         }
1737
1738         Printer = find_printer_index_by_hnd(p, r->out.handle);
1739         if ( !Printer ) {
1740                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1741                         "handle we created for printer %s\n", r->in.printername));
1742                 close_printer_handle(p, r->out.handle);
1743                 ZERO_STRUCTP(r->out.handle);
1744                 return WERR_INVALID_PARAM;
1745         }
1746
1747         /*
1748          * First case: the user is opening the print server:
1749          *
1750          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1751          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1752          *
1753          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1754          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1755          * or if the user is listed in the smb.conf printer admin parameter.
1756          *
1757          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1758          * client view printer folder, but does not show the MSAPW.
1759          *
1760          * Note: this test needs code to check access rights here too. Jeremy
1761          * could you look at this?
1762          *
1763          * Second case: the user is opening a printer:
1764          * NT doesn't let us connect to a printer if the connecting user
1765          * doesn't have print permission.
1766          *
1767          * Third case: user is opening a Port Monitor
1768          * access checks same as opening a handle to the print server.
1769          */
1770
1771         switch (Printer->printer_type )
1772         {
1773         case SPLHND_SERVER:
1774         case SPLHND_PORTMON_TCP:
1775         case SPLHND_PORTMON_LOCAL:
1776                 /* Printserver handles use global struct... */
1777
1778                 snum = -1;
1779
1780                 /* Map standard access rights to object specific access rights */
1781
1782                 se_map_standard(&r->in.access_mask,
1783                                 &printserver_std_mapping);
1784
1785                 /* Deny any object specific bits that don't apply to print
1786                    servers (i.e printer and job specific bits) */
1787
1788                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1789
1790                 if (r->in.access_mask &
1791                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1792                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1793                         close_printer_handle(p, r->out.handle);
1794                         ZERO_STRUCTP(r->out.handle);
1795                         return WERR_ACCESS_DENIED;
1796                 }
1797
1798                 /* Allow admin access */
1799
1800                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1801                 {
1802                         if (!lp_ms_add_printer_wizard()) {
1803                                 close_printer_handle(p, r->out.handle);
1804                                 ZERO_STRUCTP(r->out.handle);
1805                                 return WERR_ACCESS_DENIED;
1806                         }
1807
1808                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1809                            and not a printer admin, then fail */
1810
1811                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1812                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1813                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1814                             !token_contains_name_in_list(
1815                                     uidtoname(p->session_info->utok.uid),
1816                                     p->session_info->info3->base.domain.string,
1817                                     NULL,
1818                                     p->session_info->security_token,
1819                                     lp_printer_admin(snum))) {
1820                                 close_printer_handle(p, r->out.handle);
1821                                 ZERO_STRUCTP(r->out.handle);
1822                                 DEBUG(3,("access DENIED as user is not root, "
1823                                         "has no printoperator privilege, "
1824                                         "not a member of the printoperator builtin group and "
1825                                         "is not in printer admin list"));
1826                                 return WERR_ACCESS_DENIED;
1827                         }
1828
1829                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1830                 }
1831                 else
1832                 {
1833                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1834                 }
1835
1836                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1837                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1838
1839                 /* We fall through to return WERR_OK */
1840                 break;
1841
1842         case SPLHND_PRINTER:
1843                 /* NT doesn't let us connect to a printer if the connecting user
1844                    doesn't have print permission.  */
1845
1846                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1847                         close_printer_handle(p, r->out.handle);
1848                         ZERO_STRUCTP(r->out.handle);
1849                         return WERR_BADFID;
1850                 }
1851
1852                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1853                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1854                 }
1855
1856                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1857
1858                 /* map an empty access mask to the minimum access mask */
1859                 if (r->in.access_mask == 0x0)
1860                         r->in.access_mask = PRINTER_ACCESS_USE;
1861
1862                 /*
1863                  * If we are not serving the printer driver for this printer,
1864                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1865                  * will keep NT clients happy  --jerry
1866                  */
1867
1868                 if (lp_use_client_driver(snum)
1869                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1870                 {
1871                         r->in.access_mask = PRINTER_ACCESS_USE;
1872                 }
1873
1874                 /* check smb.conf parameters and the the sec_desc */
1875
1876                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1877                                   p->client_id->name, p->client_id->addr)) {
1878                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1879                         ZERO_STRUCTP(r->out.handle);
1880                         return WERR_ACCESS_DENIED;
1881                 }
1882
1883                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1884                                    p->session_info->security_token, snum) ||
1885                     !print_access_check(p->session_info,
1886                                         p->msg_ctx,
1887                                         snum,
1888                                         r->in.access_mask)) {
1889                         DEBUG(3, ("access DENIED for printer open\n"));
1890                         close_printer_handle(p, r->out.handle);
1891                         ZERO_STRUCTP(r->out.handle);
1892                         return WERR_ACCESS_DENIED;
1893                 }
1894
1895                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1896                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1897                         close_printer_handle(p, r->out.handle);
1898                         ZERO_STRUCTP(r->out.handle);
1899                         return WERR_ACCESS_DENIED;
1900                 }
1901
1902                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1903                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1904                 else
1905                         r->in.access_mask = PRINTER_ACCESS_USE;
1906
1907                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1908                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1909
1910                 winreg_create_printer(p->mem_ctx,
1911                                       get_session_info_system(),
1912                                       p->msg_ctx,
1913                                       lp_const_servicename(snum));
1914
1915                 break;
1916
1917         default:
1918                 /* sanity check to prevent programmer error */
1919                 ZERO_STRUCTP(r->out.handle);
1920                 return WERR_BADFID;
1921         }
1922
1923         Printer->access_granted = r->in.access_mask;
1924
1925         /*
1926          * If the client sent a devmode in the OpenPrinter() call, then
1927          * save it here in case we get a job submission on this handle
1928          */
1929
1930          if ((Printer->printer_type != SPLHND_SERVER) &&
1931              r->in.devmode_ctr.devmode) {
1932                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1933                                 &Printer->devmode);
1934          }
1935
1936 #if 0   /* JERRY -- I'm doubtful this is really effective */
1937         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1938            optimization in Windows 2000 clients  --jerry */
1939
1940         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1941                 && (RA_WIN2K == get_remote_arch()) )
1942         {
1943                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1944                 sys_usleep( 500000 );
1945         }
1946 #endif
1947
1948         return WERR_OK;
1949 }
1950
1951 /****************************************************************
1952  _spoolss_ClosePrinter
1953 ****************************************************************/
1954
1955 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1956                              struct spoolss_ClosePrinter *r)
1957 {
1958         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1959
1960         if (Printer && Printer->document_started) {
1961                 struct spoolss_EndDocPrinter e;
1962
1963                 e.in.handle = r->in.handle;
1964
1965                 _spoolss_EndDocPrinter(p, &e);
1966         }
1967
1968         if (!close_printer_handle(p, r->in.handle))
1969                 return WERR_BADFID;
1970
1971         /* clear the returned printer handle.  Observed behavior
1972            from Win2k server.  Don't think this really matters.
1973            Previous code just copied the value of the closed
1974            handle.    --jerry */
1975
1976         ZERO_STRUCTP(r->out.handle);
1977
1978         return WERR_OK;
1979 }
1980
1981 /****************************************************************
1982  _spoolss_DeletePrinter
1983 ****************************************************************/
1984
1985 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1986                               struct spoolss_DeletePrinter *r)
1987 {
1988         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1989         WERROR result;
1990         int snum;
1991
1992         if (Printer && Printer->document_started) {
1993                 struct spoolss_EndDocPrinter e;
1994
1995                 e.in.handle = r->in.handle;
1996
1997                 _spoolss_EndDocPrinter(p, &e);
1998         }
1999
2000         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2001                 winreg_delete_printer_key(p->mem_ctx,
2002                                           get_session_info_system(),
2003                                           p->msg_ctx,
2004                                           lp_const_servicename(snum),
2005                                           "");
2006         }
2007
2008         result = delete_printer_handle(p, r->in.handle);
2009
2010         return result;
2011 }
2012
2013 /*******************************************************************
2014  * static function to lookup the version id corresponding to an
2015  * long architecture string
2016  ******************************************************************/
2017
2018 static const struct print_architecture_table_node archi_table[]= {
2019
2020         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2021         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2022         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2023         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2024         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2025         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2026         {"Windows x64",          SPL_ARCH_X64,          3 },
2027         {NULL,                   "",            -1 }
2028 };
2029
2030 static int get_version_id(const char *arch)
2031 {
2032         int i;
2033
2034         for (i=0; archi_table[i].long_archi != NULL; i++)
2035         {
2036                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2037                         return (archi_table[i].version);
2038         }
2039
2040         return -1;
2041 }
2042
2043 /****************************************************************
2044  _spoolss_DeletePrinterDriver
2045 ****************************************************************/
2046
2047 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2048                                     struct spoolss_DeletePrinterDriver *r)
2049 {
2050
2051         struct spoolss_DriverInfo8 *info = NULL;
2052         struct spoolss_DriverInfo8 *info_win2k = NULL;
2053         int                             version;
2054         WERROR                          status;
2055
2056         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2057            and not a printer admin, then fail */
2058
2059         if ( (p->session_info->utok.uid != sec_initial_uid())
2060              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2061                 && !token_contains_name_in_list(
2062                         uidtoname(p->session_info->utok.uid),
2063                         p->session_info->info3->base.domain.string,
2064                         NULL,
2065                         p->session_info->security_token,
2066                         lp_printer_admin(-1)) )
2067         {
2068                 return WERR_ACCESS_DENIED;
2069         }
2070
2071         /* check that we have a valid driver name first */
2072
2073         if ((version = get_version_id(r->in.architecture)) == -1)
2074                 return WERR_INVALID_ENVIRONMENT;
2075
2076         status = winreg_get_driver(p->mem_ctx,
2077                                    get_session_info_system(),
2078                                    p->msg_ctx,
2079                                    r->in.architecture, r->in.driver,
2080                                    version, &info);
2081         if (!W_ERROR_IS_OK(status)) {
2082                 /* try for Win2k driver if "Windows NT x86" */
2083
2084                 if ( version == 2 ) {
2085                         version = 3;
2086
2087                         status = winreg_get_driver(p->mem_ctx,
2088                                                    get_session_info_system(),
2089                                                    p->msg_ctx,
2090                                                    r->in.architecture,
2091                                                    r->in.driver,
2092                                                    version, &info);
2093                         if (!W_ERROR_IS_OK(status)) {
2094                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2095                                 goto done;
2096                         }
2097                 }
2098                 /* otherwise it was a failure */
2099                 else {
2100                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2101                         goto done;
2102                 }
2103
2104         }
2105
2106         if (printer_driver_in_use(p->mem_ctx,
2107                                   get_session_info_system(),
2108                                   p->msg_ctx,
2109                                   info)) {
2110                 status = WERR_PRINTER_DRIVER_IN_USE;
2111                 goto done;
2112         }
2113
2114         if (version == 2) {
2115                 status = winreg_get_driver(p->mem_ctx,
2116                                            get_session_info_system(),
2117                                            p->msg_ctx,
2118                                            r->in.architecture,
2119                                            r->in.driver, 3, &info_win2k);
2120                 if (W_ERROR_IS_OK(status)) {
2121                         /* if we get to here, we now have 2 driver info structures to remove */
2122                         /* remove the Win2k driver first*/
2123
2124                         status = winreg_del_driver(p->mem_ctx,
2125                                                    get_session_info_system(),
2126                                                    p->msg_ctx,
2127                                                    info_win2k, 3);
2128                         talloc_free(info_win2k);
2129
2130                         /* this should not have failed---if it did, report to client */
2131                         if (!W_ERROR_IS_OK(status)) {
2132                                 goto done;
2133                         }
2134                 }
2135         }
2136
2137         status = winreg_del_driver(p->mem_ctx,
2138                                    get_session_info_system(),
2139                                    p->msg_ctx,
2140                                    info, version);
2141
2142 done:
2143         talloc_free(info);
2144
2145         return status;
2146 }
2147
2148 /****************************************************************
2149  _spoolss_DeletePrinterDriverEx
2150 ****************************************************************/
2151
2152 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2153                                       struct spoolss_DeletePrinterDriverEx *r)
2154 {
2155         struct spoolss_DriverInfo8      *info = NULL;
2156         struct spoolss_DriverInfo8      *info_win2k = NULL;
2157         int                             version;
2158         bool                            delete_files;
2159         WERROR                          status;
2160
2161         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2162            and not a printer admin, then fail */
2163
2164         if ( (p->session_info->utok.uid != sec_initial_uid())
2165                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2166                 && !token_contains_name_in_list(
2167                         uidtoname(p->session_info->utok.uid),
2168                         p->session_info->info3->base.domain.string,
2169                         NULL,
2170                         p->session_info->security_token, lp_printer_admin(-1)) )
2171         {
2172                 return WERR_ACCESS_DENIED;
2173         }
2174
2175         /* check that we have a valid driver name first */
2176         if ((version = get_version_id(r->in.architecture)) == -1) {
2177                 /* this is what NT returns */
2178                 return WERR_INVALID_ENVIRONMENT;
2179         }
2180
2181         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2182                 version = r->in.version;
2183
2184         status = winreg_get_driver(p->mem_ctx,
2185                                    get_session_info_system(),
2186                                    p->msg_ctx,
2187                                    r->in.architecture,
2188                                    r->in.driver,
2189                                    version,
2190                                    &info);
2191         if (!W_ERROR_IS_OK(status)) {
2192                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2193
2194                 /*
2195                  * if the client asked for a specific version,
2196                  * or this is something other than Windows NT x86,
2197                  * then we've failed
2198                  */
2199
2200                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2201                         goto done;
2202
2203                 /* try for Win2k driver if "Windows NT x86" */
2204
2205                 version = 3;
2206                 status = winreg_get_driver(info,
2207                                            get_session_info_system(),
2208                                            p->msg_ctx,
2209                                            r->in.architecture,
2210                                            r->in.driver,
2211                                            version, &info);
2212                 if (!W_ERROR_IS_OK(status)) {
2213                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2214                         goto done;
2215                 }
2216         }
2217
2218         if (printer_driver_in_use(info,
2219                                   get_session_info_system(),
2220                                   p->msg_ctx,
2221                                   info)) {
2222                 status = WERR_PRINTER_DRIVER_IN_USE;
2223                 goto done;
2224         }
2225
2226         /*
2227          * we have a couple of cases to consider.
2228          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2229          *     then the delete should fail if **any** files overlap with
2230          *     other drivers
2231          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2232          *     non-overlapping files
2233          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2234          *     is set, the do not delete any files
2235          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2236          */
2237
2238         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2239
2240         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2241
2242         if (delete_files &&
2243             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2244             printer_driver_files_in_use(info,
2245                                         get_session_info_system(),
2246                                         p->msg_ctx,
2247                                         info)) {
2248                 /* no idea of the correct error here */
2249                 status = WERR_ACCESS_DENIED;
2250                 goto done;
2251         }
2252
2253
2254         /* also check for W32X86/3 if necessary; maybe we already have? */
2255
2256         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2257                 status = winreg_get_driver(info,
2258                                            get_session_info_system(),
2259                                            p->msg_ctx,
2260                                            r->in.architecture,
2261                                            r->in.driver, 3, &info_win2k);
2262                 if (W_ERROR_IS_OK(status)) {
2263
2264                         if (delete_files &&
2265                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2266                             printer_driver_files_in_use(info,
2267                                                         get_session_info_system(),
2268                                                         p->msg_ctx,
2269                                                         info_win2k)) {
2270                                 /* no idea of the correct error here */
2271                                 talloc_free(info_win2k);
2272                                 status = WERR_ACCESS_DENIED;
2273                                 goto done;
2274                         }
2275
2276                         /* if we get to here, we now have 2 driver info structures to remove */
2277                         /* remove the Win2k driver first*/
2278
2279                         status = winreg_del_driver(info,
2280                                                    get_session_info_system(),
2281                                                    p->msg_ctx,
2282                                                    info_win2k,
2283                                                    3);
2284
2285                         /* this should not have failed---if it did, report to client */
2286
2287                         if (!W_ERROR_IS_OK(status)) {
2288                                 goto done;
2289                         }
2290
2291                         /*
2292                          * now delete any associated files if delete_files is
2293                          * true. Even if this part failes, we return succes
2294                          * because the driver doesn not exist any more
2295                          */
2296                         if (delete_files) {
2297                                 delete_driver_files(get_session_info_system(),
2298                                                     info_win2k);
2299                         }
2300                 }
2301         }
2302
2303         status = winreg_del_driver(info,
2304                                    get_session_info_system(),
2305                                    p->msg_ctx,
2306                                    info,
2307                                    version);
2308         if (!W_ERROR_IS_OK(status)) {
2309                 goto done;
2310         }
2311
2312         /*
2313          * now delete any associated files if delete_files is
2314          * true. Even if this part failes, we return succes
2315          * because the driver doesn not exist any more
2316          */
2317         if (delete_files) {
2318                 delete_driver_files(get_session_info_system(), info);
2319         }
2320
2321 done:
2322         talloc_free(info);
2323         return status;
2324 }
2325
2326
2327 /********************************************************************
2328  GetPrinterData on a printer server Handle.
2329 ********************************************************************/
2330
2331 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2332                                             const char *value,
2333                                             enum winreg_Type *type,
2334                                             union spoolss_PrinterData *data)
2335 {
2336         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2337
2338         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2339                 *type = REG_DWORD;
2340                 data->value = 0x00;
2341                 return WERR_OK;
2342         }
2343
2344         if (!StrCaseCmp(value, "BeepEnabled")) {
2345                 *type = REG_DWORD;
2346                 data->value = 0x00;
2347                 return WERR_OK;
2348         }
2349
2350         if (!StrCaseCmp(value, "EventLog")) {
2351                 *type = REG_DWORD;
2352                 /* formally was 0x1b */
2353                 data->value = 0x00;
2354                 return WERR_OK;
2355         }
2356
2357         if (!StrCaseCmp(value, "NetPopup")) {
2358                 *type = REG_DWORD;
2359                 data->value = 0x00;
2360                 return WERR_OK;
2361         }
2362
2363         if (!StrCaseCmp(value, "MajorVersion")) {
2364                 *type = REG_DWORD;
2365
2366                 /* Windows NT 4.0 seems to not allow uploading of drivers
2367                    to a server that reports 0x3 as the MajorVersion.
2368                    need to investigate more how Win2k gets around this .
2369                    -- jerry */
2370
2371                 if (RA_WINNT == get_remote_arch()) {
2372                         data->value = 0x02;
2373                 } else {
2374                         data->value = 0x03;
2375                 }
2376
2377                 return WERR_OK;
2378         }
2379
2380         if (!StrCaseCmp(value, "MinorVersion")) {
2381                 *type = REG_DWORD;
2382                 data->value = 0x00;
2383                 return WERR_OK;
2384         }
2385
2386         /* REG_BINARY
2387          *  uint32_t size        = 0x114
2388          *  uint32_t major       = 5
2389          *  uint32_t minor       = [0|1]
2390          *  uint32_t build       = [2195|2600]
2391          *  extra unicode string = e.g. "Service Pack 3"
2392          */
2393         if (!StrCaseCmp(value, "OSVersion")) {
2394                 DATA_BLOB blob;
2395                 enum ndr_err_code ndr_err;
2396                 struct spoolss_OSVersion os;
2397
2398                 os.major                = 5;    /* Windows 2000 == 5.0 */
2399                 os.minor                = 0;
2400                 os.build                = 2195; /* build */
2401                 os.extra_string         = "";   /* leave extra string empty */
2402
2403                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2404                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2405                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2406                         return WERR_GENERAL_FAILURE;
2407                 }
2408
2409                 *type = REG_BINARY;
2410                 data->binary = blob;
2411
2412                 return WERR_OK;
2413         }
2414
2415
2416         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2417                 *type = REG_SZ;
2418
2419                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2420                 W_ERROR_HAVE_NO_MEMORY(data->string);
2421
2422                 return WERR_OK;
2423         }
2424
2425         if (!StrCaseCmp(value, "Architecture")) {
2426                 *type = REG_SZ;
2427                 data->string = talloc_strdup(mem_ctx,
2428                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2429                 W_ERROR_HAVE_NO_MEMORY(data->string);
2430
2431                 return WERR_OK;
2432         }
2433
2434         if (!StrCaseCmp(value, "DsPresent")) {
2435                 *type = REG_DWORD;
2436
2437                 /* only show the publish check box if we are a
2438                    member of a AD domain */
2439
2440                 if (lp_security() == SEC_ADS) {
2441                         data->value = 0x01;
2442                 } else {
2443                         data->value = 0x00;
2444                 }
2445                 return WERR_OK;
2446         }
2447
2448         if (!StrCaseCmp(value, "DNSMachineName")) {
2449                 const char *hostname = get_mydnsfullname();
2450
2451                 if (!hostname) {
2452                         return WERR_BADFILE;
2453                 }
2454
2455                 *type = REG_SZ;
2456                 data->string = talloc_strdup(mem_ctx, hostname);
2457                 W_ERROR_HAVE_NO_MEMORY(data->string);
2458
2459                 return WERR_OK;
2460         }
2461
2462         *type = REG_NONE;
2463
2464         return WERR_INVALID_PARAM;
2465 }
2466
2467 /****************************************************************
2468  _spoolss_GetPrinterData
2469 ****************************************************************/
2470
2471 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2472                                struct spoolss_GetPrinterData *r)
2473 {
2474         struct spoolss_GetPrinterDataEx r2;
2475
2476         r2.in.handle            = r->in.handle;
2477         r2.in.key_name          = "PrinterDriverData";
2478         r2.in.value_name        = r->in.value_name;
2479         r2.in.offered           = r->in.offered;
2480         r2.out.type             = r->out.type;
2481         r2.out.data             = r->out.data;
2482         r2.out.needed           = r->out.needed;
2483
2484         return _spoolss_GetPrinterDataEx(p, &r2);
2485 }
2486
2487 /*********************************************************
2488  Connect to the client machine.
2489 **********************************************************/
2490
2491 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2492                         struct sockaddr_storage *client_ss, const char *remote_machine)
2493 {
2494         NTSTATUS ret;
2495         struct cli_state *the_cli;
2496         struct sockaddr_storage rm_addr;
2497         char addr[INET6_ADDRSTRLEN];
2498
2499         if ( is_zero_addr(client_ss) ) {
2500                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2501                         remote_machine));
2502                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2503                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2504                         return false;
2505                 }
2506                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2507         } else {
2508                 rm_addr = *client_ss;
2509                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2510                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2511                         addr));
2512         }
2513
2514         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2515                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2516                         addr));
2517                 return false;
2518         }
2519
2520         /* setup the connection */
2521         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2522                 &rm_addr, 0, "IPC$", "IPC",
2523                 "", /* username */
2524                 "", /* domain */
2525                 "", /* password */
2526                 0, lp_client_signing());
2527
2528         if ( !NT_STATUS_IS_OK( ret ) ) {
2529                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2530                         remote_machine ));
2531                 return false;
2532         }
2533
2534         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2535                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2536                 cli_shutdown(the_cli);
2537                 return false;
2538         }
2539
2540         /*
2541          * Ok - we have an anonymous connection to the IPC$ share.
2542          * Now start the NT Domain stuff :-).
2543          */
2544
2545         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2546         if (!NT_STATUS_IS_OK(ret)) {
2547                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2548                         remote_machine, nt_errstr(ret)));
2549                 cli_shutdown(the_cli);
2550                 return false;
2551         }
2552
2553         return true;
2554 }
2555
2556 /***************************************************************************
2557  Connect to the client.
2558 ****************************************************************************/
2559
2560 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2561                                         uint32_t localprinter,
2562                                         enum winreg_Type type,
2563                                         struct policy_handle *handle,
2564                                         struct notify_back_channel **_chan,
2565                                         struct sockaddr_storage *client_ss,
2566                                         struct messaging_context *msg_ctx)
2567 {
2568         WERROR result;
2569         NTSTATUS status;
2570         struct notify_back_channel *chan;
2571
2572         for (chan = back_channels; chan; chan = chan->next) {
2573                 if (memcmp(&chan->client_address, client_ss,
2574                            sizeof(struct sockaddr_storage)) == 0) {
2575                         break;
2576                 }
2577         }
2578
2579         /*
2580          * If it's the first connection, contact the client
2581          * and connect to the IPC$ share anonymously
2582          */
2583         if (!chan) {
2584                 fstring unix_printer;
2585
2586                 /* the +2 is to strip the leading 2 backslashs */
2587                 fstrcpy(unix_printer, printer + 2);
2588
2589                 chan = talloc_zero(back_channels, struct notify_back_channel);
2590                 if (!chan) {
2591                         return false;
2592                 }
2593                 chan->client_address = *client_ss;
2594
2595                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2596                         TALLOC_FREE(chan);
2597                         return false;
2598                 }
2599                 chan->binding_handle = chan->cli_pipe->binding_handle;
2600
2601                 DLIST_ADD(back_channels, chan);
2602
2603                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2604                                    receive_notify2_message_list);
2605                 /* Tell the connections db we're now interested in printer
2606                  * notify messages. */
2607                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2608                                             true, FLAG_MSG_PRINT_NOTIFY);
2609         }
2610
2611         /*
2612          * Tell the specific printing tdb we want messages for this printer
2613          * by registering our PID.
2614          */
2615
2616         if (!print_notify_register_pid(snum)) {
2617                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2618                           printer));
2619         }
2620
2621         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2622                                                  talloc_tos(),
2623                                                  printer,
2624                                                  localprinter,
2625                                                  type,
2626                                                  0,
2627                                                  NULL,
2628                                                  handle,
2629                                                  &result);
2630         if (!NT_STATUS_IS_OK(status)) {
2631                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2632                 result = ntstatus_to_werror(status);
2633         } else if (!W_ERROR_IS_OK(result)) {
2634                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2635         }
2636
2637         chan->active_connections++;
2638         *_chan = chan;
2639
2640         return (W_ERROR_IS_OK(result));
2641 }
2642
2643 /****************************************************************
2644  ****************************************************************/
2645
2646 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2647                                                              const struct spoolss_NotifyOption *r)
2648 {
2649         struct spoolss_NotifyOption *option;
2650         uint32_t i,k;
2651
2652         if (!r) {
2653                 return NULL;
2654         }
2655
2656         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2657         if (!option) {
2658                 return NULL;
2659         }
2660
2661         *option = *r;
2662
2663         if (!option->count) {
2664                 return option;
2665         }
2666
2667         option->types = talloc_zero_array(option,
2668                 struct spoolss_NotifyOptionType, option->count);
2669         if (!option->types) {
2670                 talloc_free(option);
2671                 return NULL;
2672         }
2673
2674         for (i=0; i < option->count; i++) {
2675                 option->types[i] = r->types[i];
2676
2677                 if (option->types[i].count) {
2678                         option->types[i].fields = talloc_zero_array(option,
2679                                 union spoolss_Field, option->types[i].count);
2680                         if (!option->types[i].fields) {
2681                                 talloc_free(option);
2682                                 return NULL;
2683                         }
2684                         for (k=0; k<option->types[i].count; k++) {
2685                                 option->types[i].fields[k] =
2686                                         r->types[i].fields[k];
2687                         }
2688                 }
2689         }
2690
2691         return option;
2692 }
2693
2694 /****************************************************************
2695  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2696  *
2697  * before replying OK: status=0 a rpc call is made to the workstation
2698  * asking ReplyOpenPrinter
2699  *
2700  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2701  * called from api_spoolss_rffpcnex
2702 ****************************************************************/
2703
2704 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2705                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2706 {
2707         int snum = -1;
2708         struct spoolss_NotifyOption *option = r->in.notify_options;
2709         struct sockaddr_storage client_ss;
2710
2711         /* store the notify value in the printer struct */
2712
2713         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2714
2715         if (!Printer) {
2716                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2717                         "Invalid handle (%s:%u:%u).\n",
2718                         OUR_HANDLE(r->in.handle)));
2719                 return WERR_BADFID;
2720         }
2721
2722         Printer->notify.flags           = r->in.flags;
2723         Printer->notify.options         = r->in.options;
2724         Printer->notify.printerlocal    = r->in.printer_local;
2725         Printer->notify.msg_ctx         = p->msg_ctx;
2726
2727         TALLOC_FREE(Printer->notify.option);
2728         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2729
2730         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2731
2732         /* Connect to the client machine and send a ReplyOpenPrinter */
2733
2734         if ( Printer->printer_type == SPLHND_SERVER)
2735                 snum = -1;
2736         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2737                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2738                 return WERR_BADFID;
2739
2740         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2741                 "client_address is %s\n", p->client_id->addr));
2742
2743         if (!lp_print_notify_backchannel(snum)) {
2744                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2745                         "backchannel disabled\n"));
2746                 return WERR_SERVER_UNAVAILABLE;
2747         }
2748
2749         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2750                                    AI_NUMERICHOST)) {
2751                 return WERR_SERVER_UNAVAILABLE;
2752         }
2753
2754         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2755                                         Printer->notify.printerlocal, REG_SZ,
2756                                         &Printer->notify.cli_hnd,
2757                                         &Printer->notify.cli_chan,
2758                                         &client_ss, p->msg_ctx)) {
2759                 return WERR_SERVER_UNAVAILABLE;
2760         }
2761
2762         return WERR_OK;
2763 }
2764
2765 /*******************************************************************
2766  * fill a notify_info_data with the servername
2767  ********************************************************************/
2768
2769 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2770                                        int snum,
2771                                        struct spoolss_Notify *data,
2772                                        print_queue_struct *queue,
2773                                        struct spoolss_PrinterInfo2 *pinfo2,
2774                                        TALLOC_CTX *mem_ctx)
2775 {
2776         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2777 }
2778
2779 /*******************************************************************
2780  * fill a notify_info_data with the printername (not including the servername).
2781  ********************************************************************/
2782
2783 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2784                                         int snum,
2785                                         struct spoolss_Notify *data,
2786                                         print_queue_struct *queue,
2787                                         struct spoolss_PrinterInfo2 *pinfo2,
2788                                         TALLOC_CTX *mem_ctx)
2789 {
2790         /* the notify name should not contain the \\server\ part */
2791         const char *p = strrchr(pinfo2->printername, '\\');
2792
2793         if (!p) {
2794                 p = pinfo2->printername;
2795         } else {
2796                 p++;
2797         }
2798
2799         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2800 }
2801
2802 /*******************************************************************
2803  * fill a notify_info_data with the servicename
2804  ********************************************************************/
2805
2806 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2807                                       int snum,
2808                                       struct spoolss_Notify *data,
2809                                       print_queue_struct *queue,
2810                                       struct spoolss_PrinterInfo2 *pinfo2,
2811                                       TALLOC_CTX *mem_ctx)
2812 {
2813         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2814 }
2815
2816 /*******************************************************************
2817  * fill a notify_info_data with the port name
2818  ********************************************************************/
2819
2820 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2821                                      int snum,
2822                                      struct spoolss_Notify *data,
2823                                      print_queue_struct *queue,
2824                                      struct spoolss_PrinterInfo2 *pinfo2,
2825                                      TALLOC_CTX *mem_ctx)
2826 {
2827         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2828 }
2829
2830 /*******************************************************************
2831  * fill a notify_info_data with the printername
2832  * but it doesn't exist, have to see what to do
2833  ********************************************************************/
2834
2835 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2836                                        int snum,
2837                                        struct spoolss_Notify *data,
2838                                        print_queue_struct *queue,
2839                                        struct spoolss_PrinterInfo2 *pinfo2,
2840                                        TALLOC_CTX *mem_ctx)
2841 {
2842         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2843 }
2844
2845 /*******************************************************************
2846  * fill a notify_info_data with the comment
2847  ********************************************************************/
2848
2849 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2850                                    int snum,
2851                                    struct spoolss_Notify *data,
2852                                    print_queue_struct *queue,
2853                                    struct spoolss_PrinterInfo2 *pinfo2,
2854                                    TALLOC_CTX *mem_ctx)
2855 {
2856         const char *p;
2857
2858         if (*pinfo2->comment == '\0') {
2859                 p = lp_comment(snum);
2860         } else {
2861                 p = pinfo2->comment;
2862         }
2863
2864         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2865 }
2866
2867 /*******************************************************************
2868  * fill a notify_info_data with the comment
2869  * location = "Room 1, floor 2, building 3"
2870  ********************************************************************/
2871
2872 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2873                                     int snum,
2874                                     struct spoolss_Notify *data,
2875                                     print_queue_struct *queue,
2876                                     struct spoolss_PrinterInfo2 *pinfo2,
2877                                     TALLOC_CTX *mem_ctx)
2878 {
2879         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2880 }
2881
2882 /*******************************************************************
2883  * fill a notify_info_data with the device mode
2884  * jfm:xxxx don't to it for know but that's a real problem !!!
2885  ********************************************************************/
2886
2887 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2888                                    int snum,
2889                                    struct spoolss_Notify *data,
2890                                    print_queue_struct *queue,
2891                                    struct spoolss_PrinterInfo2 *pinfo2,
2892                                    TALLOC_CTX *mem_ctx)
2893 {
2894         /* for a dummy implementation we have to zero the fields */
2895         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2896 }
2897
2898 /*******************************************************************
2899  * fill a notify_info_data with the separator file name
2900  ********************************************************************/
2901
2902 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2903                                    int snum,
2904                                    struct spoolss_Notify *data,
2905                                    print_queue_struct *queue,
2906                                    struct spoolss_PrinterInfo2 *pinfo2,
2907                                    TALLOC_CTX *mem_ctx)
2908 {
2909         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2910 }
2911
2912 /*******************************************************************
2913  * fill a notify_info_data with the print processor
2914  * jfm:xxxx return always winprint to indicate we don't do anything to it
2915  ********************************************************************/
2916
2917 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2918                                            int snum,
2919                                            struct spoolss_Notify *data,
2920                                            print_queue_struct *queue,
2921                                            struct spoolss_PrinterInfo2 *pinfo2,
2922                                            TALLOC_CTX *mem_ctx)
2923 {
2924         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2925 }
2926
2927 /*******************************************************************
2928  * fill a notify_info_data with the print processor options
2929  * jfm:xxxx send an empty string
2930  ********************************************************************/
2931
2932 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2933                                       int snum,
2934                                       struct spoolss_Notify *data,
2935                                       print_queue_struct *queue,
2936                                       struct spoolss_PrinterInfo2 *pinfo2,
2937                                       TALLOC_CTX *mem_ctx)
2938 {
2939         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2940 }
2941
2942 /*******************************************************************
2943  * fill a notify_info_data with the data type
2944  * jfm:xxxx always send RAW as data type
2945  ********************************************************************/
2946
2947 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2948                                     int snum,
2949                                     struct spoolss_Notify *data,
2950                                     print_queue_struct *queue,
2951                                     struct spoolss_PrinterInfo2 *pinfo2,
2952                                     TALLOC_CTX *mem_ctx)
2953 {
2954         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2955 }
2956
2957 /*******************************************************************
2958  * fill a notify_info_data with the security descriptor
2959  * jfm:xxxx send an null pointer to say no security desc
2960  * have to implement security before !
2961  ********************************************************************/
2962
2963 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2964                                          int snum,
2965                                          struct spoolss_Notify *data,
2966                                          print_queue_struct *queue,
2967                                          struct spoolss_PrinterInfo2 *pinfo2,
2968                                          TALLOC_CTX *mem_ctx)
2969 {
2970         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2971 }
2972
2973 /*******************************************************************
2974  * fill a notify_info_data with the attributes
2975  * jfm:xxxx a samba printer is always shared
2976  ********************************************************************/
2977
2978 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2979                                       int snum,
2980                                       struct spoolss_Notify *data,
2981                                       print_queue_struct *queue,
2982                                       struct spoolss_PrinterInfo2 *pinfo2,
2983                                       TALLOC_CTX *mem_ctx)
2984 {
2985         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2986 }
2987
2988 /*******************************************************************
2989  * fill a notify_info_data with the priority
2990  ********************************************************************/
2991
2992 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2993                                     int snum,
2994                                     struct spoolss_Notify *data,
2995                                     print_queue_struct *queue,
2996                                     struct spoolss_PrinterInfo2 *pinfo2,
2997                                     TALLOC_CTX *mem_ctx)
2998 {
2999         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3000 }
3001
3002 /*******************************************************************
3003  * fill a notify_info_data with the default priority
3004  ********************************************************************/
3005
3006 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3007                                             int snum,
3008                                             struct spoolss_Notify *data,
3009                                             print_queue_struct *queue,
3010                                             struct spoolss_PrinterInfo2 *pinfo2,
3011                                             TALLOC_CTX *mem_ctx)
3012 {
3013         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3014 }
3015
3016 /*******************************************************************
3017  * fill a notify_info_data with the start time
3018  ********************************************************************/
3019
3020 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3021                                       int snum,
3022                                       struct spoolss_Notify *data,
3023                                       print_queue_struct *queue,
3024                                       struct spoolss_PrinterInfo2 *pinfo2,
3025                                       TALLOC_CTX *mem_ctx)
3026 {
3027         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3028 }
3029
3030 /*******************************************************************
3031  * fill a notify_info_data with the until time
3032  ********************************************************************/
3033
3034 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3035                                       int snum,
3036                                       struct spoolss_Notify *data,
3037                                       print_queue_struct *queue,
3038                                       struct spoolss_PrinterInfo2 *pinfo2,
3039                                       TALLOC_CTX *mem_ctx)
3040 {
3041         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3042 }
3043
3044 /*******************************************************************
3045  * fill a notify_info_data with the status
3046  ********************************************************************/
3047
3048 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3049                                   int snum,
3050                                   struct spoolss_Notify *data,
3051                                   print_queue_struct *queue,
3052                                   struct spoolss_PrinterInfo2 *pinfo2,
3053                                   TALLOC_CTX *mem_ctx)
3054 {
3055         print_status_struct status;
3056
3057         print_queue_length(msg_ctx, snum, &status);
3058         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3059 }
3060
3061 /*******************************************************************
3062  * fill a notify_info_data with the number of jobs queued
3063  ********************************************************************/
3064
3065 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3066                                  int snum,
3067                                  struct spoolss_Notify *data,
3068                                  print_queue_struct *queue,
3069                                  struct spoolss_PrinterInfo2 *pinfo2,
3070                                  TALLOC_CTX *mem_ctx)
3071 {
3072         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3073                 data, print_queue_length(msg_ctx, snum, NULL));
3074 }
3075
3076 /*******************************************************************
3077  * fill a notify_info_data with the average ppm
3078  ********************************************************************/
3079
3080 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3081                                        int snum,
3082                                        struct spoolss_Notify *data,
3083                                        print_queue_struct *queue,
3084                                        struct spoolss_PrinterInfo2 *pinfo2,
3085                                        TALLOC_CTX *mem_ctx)
3086 {
3087         /* always respond 8 pages per minutes */
3088         /* a little hard ! */
3089         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3090 }
3091
3092 /*******************************************************************
3093  * fill a notify_info_data with username
3094  ********************************************************************/
3095
3096 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3097                                     int snum,
3098                                     struct spoolss_Notify *data,
3099                                     print_queue_struct *queue,
3100                                     struct spoolss_PrinterInfo2 *pinfo2,
3101                                     TALLOC_CTX *mem_ctx)
3102 {
3103         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3104 }
3105
3106 /*******************************************************************
3107  * fill a notify_info_data with job status
3108  ********************************************************************/
3109
3110 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3111                                       int snum,
3112                                       struct spoolss_Notify *data,
3113                                       print_queue_struct *queue,
3114                                       struct spoolss_PrinterInfo2 *pinfo2,
3115                                       TALLOC_CTX *mem_ctx)
3116 {
3117         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3118 }
3119
3120 /*******************************************************************
3121  * fill a notify_info_data with job name
3122  ********************************************************************/
3123
3124 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3125                                     int snum,
3126                                     struct spoolss_Notify *data,
3127                                     print_queue_struct *queue,
3128                                     struct spoolss_PrinterInfo2 *pinfo2,
3129                                     TALLOC_CTX *mem_ctx)
3130 {
3131         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3132 }
3133
3134 /*******************************************************************
3135  * fill a notify_info_data with job status
3136  ********************************************************************/
3137
3138 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3139                                              int snum,
3140                                              struct spoolss_Notify *data,
3141                                              print_queue_struct *queue,
3142                                              struct spoolss_PrinterInfo2 *pinfo2,
3143                                              TALLOC_CTX *mem_ctx)
3144 {
3145         /*
3146          * Now we're returning job status codes we just return a "" here. JRA.
3147          */
3148
3149         const char *p = "";
3150
3151 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3152         p = "unknown";
3153
3154         switch (queue->status) {
3155         case LPQ_QUEUED:
3156                 p = "Queued";
3157                 break;
3158         case LPQ_PAUSED:
3159                 p = "";    /* NT provides the paused string */
3160                 break;
3161         case LPQ_SPOOLING:
3162                 p = "Spooling";
3163                 break;
3164         case LPQ_PRINTING:
3165                 p = "Printing";
3166                 break;
3167         }
3168 #endif /* NO LONGER NEEDED. */
3169
3170         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3171 }
3172
3173 /*******************************************************************
3174  * fill a notify_info_data with job time
3175  ********************************************************************/
3176
3177 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3178                                     int snum,
3179                                     struct spoolss_Notify *data,
3180                                     print_queue_struct *queue,
3181                                     struct spoolss_PrinterInfo2 *pinfo2,
3182                                     TALLOC_CTX *mem_ctx)
3183 {
3184         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3185 }
3186
3187 /*******************************************************************
3188  * fill a notify_info_data with job size
3189  ********************************************************************/
3190
3191 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3192                                     int snum,
3193                                     struct spoolss_Notify *data,
3194                                     print_queue_struct *queue,
3195                                     struct spoolss_PrinterInfo2 *pinfo2,
3196                                     TALLOC_CTX *mem_ctx)
3197 {
3198         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3199 }
3200
3201 /*******************************************************************
3202  * fill a notify_info_data with page info
3203  ********************************************************************/
3204 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3205                                        int snum,
3206                                 struct spoolss_Notify *data,
3207                                 print_queue_struct *queue,
3208                                 struct spoolss_PrinterInfo2 *pinfo2,
3209                                 TALLOC_CTX *mem_ctx)
3210 {
3211         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3212 }
3213
3214 /*******************************************************************
3215  * fill a notify_info_data with pages printed info.
3216  ********************************************************************/
3217 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3218                                          int snum,
3219                                 struct spoolss_Notify *data,
3220                                 print_queue_struct *queue,
3221                                 struct spoolss_PrinterInfo2 *pinfo2,
3222                                 TALLOC_CTX *mem_ctx)
3223 {
3224         /* Add code when back-end tracks this */
3225         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3226 }
3227
3228 /*******************************************************************
3229  Fill a notify_info_data with job position.
3230  ********************************************************************/
3231
3232 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3233                                         int snum,
3234                                         struct spoolss_Notify *data,
3235                                         print_queue_struct *queue,
3236                                         struct spoolss_PrinterInfo2 *pinfo2,
3237                                         TALLOC_CTX *mem_ctx)
3238 {
3239         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3240 }
3241
3242 /*******************************************************************
3243  Fill a notify_info_data with submitted time.
3244  ********************************************************************/
3245
3246 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3247                                           int snum,
3248                                           struct spoolss_Notify *data,
3249                                           print_queue_struct *queue,
3250                                           struct spoolss_PrinterInfo2 *pinfo2,
3251                                           TALLOC_CTX *mem_ctx)
3252 {
3253         data->data.string.string = NULL;
3254         data->data.string.size = 0;
3255
3256         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3257                                &data->data.string.string,
3258                                &data->data.string.size);
3259
3260 }
3261
3262 struct s_notify_info_data_table
3263 {
3264         enum spoolss_NotifyType type;
3265         uint16_t field;
3266         const char *name;
3267         enum spoolss_NotifyTable variable_type;
3268         void (*fn) (struct messaging_context *msg_ctx,
3269                     int snum, struct spoolss_Notify *data,
3270                     print_queue_struct *queue,
3271                     struct spoolss_PrinterInfo2 *pinfo2,
3272                     TALLOC_CTX *mem_ctx);
3273 };
3274
3275 /* A table describing the various print notification constants and
3276    whether the notification data is a pointer to a variable sized
3277    buffer, a one value uint32_t or a two value uint32_t. */
3278
3279 static const struct s_notify_info_data_table notify_info_data_table[] =
3280 {
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3316 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3317 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3318 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3319 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3320 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3321 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3322 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3323 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3324 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3325 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3326 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3327 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3328 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3329 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3330 };
3331
3332 /*******************************************************************
3333  Return the variable_type of info_data structure.
3334 ********************************************************************/
3335
3336 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3337                                                                   uint16_t field)
3338 {
3339         int i=0;
3340
3341         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3342                 if ( (notify_info_data_table[i].type == type) &&
3343                      (notify_info_data_table[i].field == field) ) {
3344                         return notify_info_data_table[i].variable_type;
3345                 }
3346         }
3347
3348         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3349
3350         return (enum spoolss_NotifyTable) 0;
3351 }
3352
3353 /****************************************************************************
3354 ****************************************************************************/
3355
3356 static bool search_notify(enum spoolss_NotifyType type,
3357                           uint16_t field,
3358                           int *value)
3359 {
3360         int i;
3361
3362         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3363                 if (notify_info_data_table[i].type == type &&
3364                     notify_info_data_table[i].field == field &&
3365                     notify_info_data_table[i].fn != NULL) {
3366                         *value = i;
3367                         return true;
3368                 }
3369         }
3370
3371         return false;
3372 }
3373
3374 /****************************************************************************
3375 ****************************************************************************/
3376
3377 static void construct_info_data(struct spoolss_Notify *info_data,
3378                                 enum spoolss_NotifyType type,
3379                                 uint16_t field, int id)
3380 {
3381         info_data->type                 = type;
3382         info_data->field.field          = field;
3383         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3384         info_data->job_id               = id;
3385 }
3386
3387 /*******************************************************************
3388  *
3389  * fill a notify_info struct with info asked
3390  *
3391  ********************************************************************/
3392
3393 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3394                                           struct printer_handle *print_hnd,
3395                                           struct spoolss_NotifyInfo *info,
3396                                           struct spoolss_PrinterInfo2 *pinfo2,
3397                                           int snum,
3398                                           const struct spoolss_NotifyOptionType *option_type,
3399                                           uint32_t id,
3400                                           TALLOC_CTX *mem_ctx)
3401 {
3402         int field_num,j;
3403         enum spoolss_NotifyType type;
3404         uint16_t field;
3405
3406         struct spoolss_Notify *current_data;
3407         print_queue_struct *queue=NULL;
3408
3409         type = option_type->type;
3410
3411         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3412                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3413                 option_type->count, lp_servicename(snum)));
3414
3415         for(field_num=0; field_num < option_type->count; field_num++) {
3416                 field = option_type->fields[field_num].field;
3417
3418                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3419
3420                 if (!search_notify(type, field, &j) )
3421                         continue;
3422
3423                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3424                                                       struct spoolss_Notify,
3425                                                       info->count + 1);
3426                 if (info->notifies == NULL) {
3427                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3428                         return false;
3429                 }
3430
3431                 current_data = &info->notifies[info->count];
3432
3433                 construct_info_data(current_data, type, field, id);
3434
3435                 DEBUG(10, ("construct_notify_printer_info: "
3436                            "calling [%s]  snum=%d  printername=[%s])\n",
3437                            notify_info_data_table[j].name, snum,
3438                            pinfo2->printername));
3439
3440                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3441                                              queue, pinfo2, mem_ctx);
3442
3443                 info->count++;
3444         }
3445
3446         return true;
3447 }
3448
3449 /*******************************************************************
3450  *
3451  * fill a notify_info struct with info asked
3452  *
3453  ********************************************************************/
3454
3455 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3456                                        print_queue_struct *queue,
3457                                        struct spoolss_NotifyInfo *info,
3458                                        struct spoolss_PrinterInfo2 *pinfo2,
3459                                        int snum,
3460                                        const struct spoolss_NotifyOptionType *option_type,
3461                                        uint32_t id,
3462                                        TALLOC_CTX *mem_ctx)
3463 {
3464         int field_num,j;
3465         enum spoolss_NotifyType type;
3466         uint16_t field;
3467         struct spoolss_Notify *current_data;
3468
3469         DEBUG(4,("construct_notify_jobs_info\n"));
3470
3471         type = option_type->type;
3472
3473         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3474                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3475                 option_type->count));
3476
3477         for(field_num=0; field_num<option_type->count; field_num++) {
3478                 field = option_type->fields[field_num].field;
3479
3480                 if (!search_notify(type, field, &j) )
3481                         continue;
3482
3483                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3484                                                       struct spoolss_Notify,
3485                                                       info->count + 1);
3486                 if (info->notifies == NULL) {
3487                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3488                         return false;
3489                 }
3490
3491                 current_data=&(info->notifies[info->count]);
3492
3493                 construct_info_data(current_data, type, field, id);
3494                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3495                                              queue, pinfo2, mem_ctx);
3496                 info->count++;
3497         }
3498
3499         return true;
3500 }
3501
3502 /*
3503  * JFM: The enumeration is not that simple, it's even non obvious.
3504  *
3505  * let's take an example: I want to monitor the PRINTER SERVER for
3506  * the printer's name and the number of jobs currently queued.
3507  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3508  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3509  *
3510  * I have 3 printers on the back of my server.
3511  *
3512  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3513  * structures.
3514  *   Number     Data                    Id
3515  *      1       printer 1 name          1
3516  *      2       printer 1 cjob          1
3517  *      3       printer 2 name          2
3518  *      4       printer 2 cjob          2
3519  *      5       printer 3 name          3
3520  *      6       printer 3 name          3
3521  *
3522  * that's the print server case, the printer case is even worse.
3523  */
3524
3525 /*******************************************************************
3526  *
3527  * enumerate all printers on the printserver
3528  * fill a notify_info struct with info asked
3529  *
3530  ********************************************************************/
3531
3532 static WERROR printserver_notify_info(struct pipes_struct *p,
3533                                       struct policy_handle *hnd,
3534                                       struct spoolss_NotifyInfo *info,
3535                                       TALLOC_CTX *mem_ctx)
3536 {
3537         int snum;
3538         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3539         int n_services=lp_numservices();
3540         int i;
3541         struct spoolss_NotifyOption *option;
3542         struct spoolss_NotifyOptionType option_type;
3543         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3544         WERROR result;
3545
3546         DEBUG(4,("printserver_notify_info\n"));
3547
3548         if (!Printer)
3549                 return WERR_BADFID;
3550
3551         option = Printer->notify.option;
3552
3553         info->version   = 2;
3554         info->notifies  = NULL;
3555         info->count     = 0;
3556
3557         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3558            sending a ffpcn() request first */
3559
3560         if ( !option )
3561                 return WERR_BADFID;
3562
3563         for (i=0; i<option->count; i++) {
3564                 option_type = option->types[i];
3565
3566                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3567                         continue;
3568
3569                 for (snum = 0; snum < n_services; snum++) {
3570                         if (!lp_browseable(snum) ||
3571                             !lp_snum_ok(snum) ||
3572                             !lp_print_ok(snum)) {
3573                                 continue; /* skip */
3574                         }
3575
3576                         /* Maybe we should use the SYSTEM session_info here... */
3577                         result = winreg_get_printer(mem_ctx,
3578                                                     get_session_info_system(),
3579                                                     p->msg_ctx,
3580                                                     lp_servicename(snum),
3581                                                     &pinfo2);
3582                         if (!W_ERROR_IS_OK(result)) {
3583                                 DEBUG(4, ("printserver_notify_info: "
3584                                           "Failed to get printer [%s]\n",
3585                                           lp_servicename(snum)));
3586                                 continue;
3587                         }
3588
3589
3590                         construct_notify_printer_info(p->msg_ctx,
3591                                                       Printer, info,
3592                                                       pinfo2, snum,
3593                                                       &option_type, snum,
3594                                                       mem_ctx);
3595
3596                         TALLOC_FREE(pinfo2);
3597                 }
3598         }
3599
3600 #if 0
3601         /*
3602          * Debugging information, don't delete.
3603          */
3604
3605         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3606         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3607         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3608
3609         for (i=0; i<info->count; i++) {
3610                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3611                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3612                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3613         }
3614 #endif
3615
3616         return WERR_OK;
3617 }
3618
3619 /*******************************************************************
3620  *
3621  * fill a notify_info struct with info asked
3622  *
3623  ********************************************************************/
3624
3625 static WERROR printer_notify_info(struct pipes_struct *p,
3626                                   struct policy_handle *hnd,
3627                                   struct spoolss_NotifyInfo *info,
3628                                   TALLOC_CTX *mem_ctx)
3629 {
3630         int snum;
3631         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3632         int i;
3633         uint32_t id;
3634         struct spoolss_NotifyOption *option;
3635         struct spoolss_NotifyOptionType option_type;
3636         int count,j;
3637         print_queue_struct *queue=NULL;
3638         print_status_struct status;
3639         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3640         WERROR result;
3641
3642         DEBUG(4,("printer_notify_info\n"));
3643
3644         if (!Printer)
3645                 return WERR_BADFID;
3646
3647         option = Printer->notify.option;
3648         id = 0x0;
3649
3650         info->version   = 2;
3651         info->notifies  = NULL;
3652         info->count     = 0;
3653
3654         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3655            sending a ffpcn() request first */
3656
3657         if ( !option )
3658                 return WERR_BADFID;
3659
3660         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3661                 return WERR_BADFID;
3662         }
3663
3664         /* Maybe we should use the SYSTEM session_info here... */
3665         result = winreg_get_printer(mem_ctx,
3666                                     get_session_info_system(),
3667                                     p->msg_ctx,
3668                                     lp_servicename(snum), &pinfo2);
3669         if (!W_ERROR_IS_OK(result)) {
3670                 return WERR_BADFID;
3671         }
3672
3673         for (i=0; i<option->count; i++) {
3674                 option_type = option->types[i];
3675
3676                 switch (option_type.type) {
3677                 case PRINTER_NOTIFY_TYPE:
3678                         if (construct_notify_printer_info(p->msg_ctx,
3679                                                           Printer, info,
3680                                                           pinfo2, snum,
3681                                                           &option_type, id,
3682                                                           mem_ctx)) {
3683                                 id--;
3684                         }
3685                         break;
3686
3687                 case JOB_NOTIFY_TYPE:
3688
3689                         count = print_queue_status(p->msg_ctx, snum, &queue,
3690                                                    &status);
3691
3692                         for (j=0; j<count; j++) {
3693                                 construct_notify_jobs_info(p->msg_ctx,
3694                                                            &queue[j], info,
3695                                                            pinfo2, snum,
3696                                                            &option_type,
3697                                                            queue[j].job,
3698                                                            mem_ctx);
3699                         }
3700
3701                         SAFE_FREE(queue);
3702                         break;
3703                 }
3704         }
3705
3706         /*
3707          * Debugging information, don't delete.
3708          */
3709         /*
3710         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3711         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3712         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3713
3714         for (i=0; i<info->count; i++) {
3715                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3716                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3717                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3718         }
3719         */
3720
3721         talloc_free(pinfo2);
3722         return WERR_OK;
3723 }
3724
3725 /****************************************************************
3726  _spoolss_RouterRefreshPrinterChangeNotify
3727 ****************************************************************/
3728
3729 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3730                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3731 {
3732         struct spoolss_NotifyInfo *info;
3733
3734         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3735         WERROR result = WERR_BADFID;
3736
3737         /* we always have a spoolss_NotifyInfo struct */
3738         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3739         if (!info) {
3740                 result = WERR_NOMEM;
3741                 goto done;
3742         }
3743
3744         *r->out.info = info;
3745
3746         if (!Printer) {
3747                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3748                         "Invalid handle (%s:%u:%u).\n",
3749                         OUR_HANDLE(r->in.handle)));
3750                 goto done;
3751         }
3752
3753         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3754
3755         /*
3756          *      We are now using the change value, and
3757          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3758          *      I don't have a global notification system, I'm sending back all the
3759          *      information even when _NOTHING_ has changed.
3760          */
3761
3762         /* We need to keep track of the change value to send back in
3763            RRPCN replies otherwise our updates are ignored. */
3764
3765         Printer->notify.fnpcn = true;
3766
3767         if (Printer->notify.cli_chan != NULL &&
3768             Printer->notify.cli_chan->active_connections > 0) {
3769                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3770                         "Saving change value in request [%x]\n",
3771                         r->in.change_low));
3772                 Printer->notify.change = r->in.change_low;
3773         }
3774
3775         /* just ignore the spoolss_NotifyOption */
3776
3777         switch (Printer->printer_type) {
3778                 case SPLHND_SERVER:
3779                         result = printserver_notify_info(p, r->in.handle,
3780                                                          info, p->mem_ctx);
3781                         break;
3782
3783                 case SPLHND_PRINTER:
3784                         result = printer_notify_info(p, r->in.handle,
3785                                                      info, p->mem_ctx);
3786                         break;
3787         }
3788
3789         Printer->notify.fnpcn = false;
3790
3791 done:
3792         return result;
3793 }
3794
3795 /********************************************************************
3796  ********************************************************************/
3797
3798 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3799                                  const char *servername,
3800                                  const char *printername,
3801                                  const char **printername_p)
3802 {
3803         /* FIXME: add lp_force_printername() */
3804
3805         if (servername == NULL) {
3806                 *printername_p = talloc_strdup(mem_ctx, printername);
3807                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3808                 return WERR_OK;
3809         }
3810
3811         if (servername[0] == '\\' && servername[1] == '\\') {
3812                 servername += 2;
3813         }
3814
3815         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3816         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3817
3818         return WERR_OK;
3819 }
3820
3821 /********************************************************************
3822  ********************************************************************/
3823
3824 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3825                                           const char *printername)
3826 {
3827         if (dm == NULL) {
3828                 return;
3829         }
3830
3831         dm->devicename = talloc_strndup(dm, printername,
3832                                         MIN(strlen(printername), 31));
3833 }
3834
3835 /********************************************************************
3836  * construct_printer_info_0
3837  * fill a printer_info_0 struct
3838  ********************************************************************/
3839
3840 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3841                                       const struct auth_serversupplied_info *session_info,
3842                                       struct messaging_context *msg_ctx,
3843                                       struct spoolss_PrinterInfo2 *info2,
3844                                       const char *servername,
3845                                       struct spoolss_PrinterInfo0 *r,
3846                                       int snum)
3847 {
3848         int count;
3849         struct printer_session_counter *session_counter;
3850         struct timeval setuptime;
3851         print_status_struct status;
3852         WERROR result;
3853
3854         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3855         if (!W_ERROR_IS_OK(result)) {
3856                 return result;
3857         }
3858
3859         if (servername) {
3860                 r->servername = talloc_strdup(mem_ctx, servername);
3861                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3862         } else {
3863                 r->servername = NULL;
3864         }
3865
3866         count = print_queue_length(msg_ctx, snum, &status);
3867
3868         /* check if we already have a counter for this printer */
3869         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3870                 if (session_counter->snum == snum)
3871                         break;
3872         }
3873
3874         /* it's the first time, add it to the list */
3875         if (session_counter == NULL) {
3876                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3877                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3878                 session_counter->snum           = snum;
3879                 session_counter->counter        = 0;
3880                 DLIST_ADD(counter_list, session_counter);
3881         }
3882
3883         /* increment it */
3884         session_counter->counter++;
3885
3886         r->cjobs                        = count;
3887         r->total_jobs                   = 0;
3888         r->total_bytes                  = 0;
3889
3890         get_startup_time(&setuptime);
3891         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3892
3893         /* JFM:
3894          * the global_counter should be stored in a TDB as it's common to all the clients
3895          * and should be zeroed on samba startup
3896          */
3897         r->global_counter               = session_counter->counter;
3898         r->total_pages                  = 0;
3899         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3900         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3901         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3902         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3903         r->spooling                     = 0;
3904         r->max_spooling                 = 0;
3905         r->session_counter              = session_counter->counter;
3906         r->num_error_out_of_paper       = 0x0;
3907         r->num_error_not_ready          = 0x0;          /* number of print failure */
3908         r->job_error                    = 0x0;
3909         r->number_of_processors         = 0x1;
3910         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3911         r->high_part_total_bytes        = 0x0;
3912
3913         /* ChangeID in milliseconds*/
3914         winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3915                                     info2->sharename, &r->change_id);
3916
3917         r->last_error                   = WERR_OK;
3918         r->status                       = nt_printq_status(status.status);
3919         r->enumerate_network_printers   = 0x0;
3920         r->c_setprinter                 = 0x0;
3921         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3922         r->processor_level              = 0x6;          /* 6  ???*/
3923         r->ref_ic                       = 0;
3924         r->reserved2                    = 0;
3925         r->reserved3                    = 0;
3926
3927         return WERR_OK;
3928 }
3929
3930
3931 /********************************************************************
3932  * construct_printer_info1
3933  * fill a spoolss_PrinterInfo1 struct
3934 ********************************************************************/
3935
3936 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3937                                       const struct spoolss_PrinterInfo2 *info2,
3938                                       uint32_t flags,
3939                                       const char *servername,
3940                                       struct spoolss_PrinterInfo1 *r,
3941                                       int snum)
3942 {
3943         WERROR result;
3944
3945         r->flags                = flags;
3946
3947         if (info2->comment == NULL || info2->comment[0] == '\0') {
3948                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3949         } else {
3950                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3951         }
3952         W_ERROR_HAVE_NO_MEMORY(r->comment);
3953
3954         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3955         if (!W_ERROR_IS_OK(result)) {
3956                 return result;
3957         }
3958
3959         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3960                                                   r->name,
3961                                                   info2->drivername,
3962                                                   r->comment);
3963         W_ERROR_HAVE_NO_MEMORY(r->description);
3964
3965         return WERR_OK;
3966 }
3967
3968 /********************************************************************
3969  * construct_printer_info2
3970  * fill a spoolss_PrinterInfo2 struct
3971 ********************************************************************/
3972
3973 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3974                                       struct messaging_context *msg_ctx,
3975                                       const struct spoolss_PrinterInfo2 *info2,
3976                                       const char *servername,
3977                                       struct spoolss_PrinterInfo2 *r,
3978                                       int snum)
3979 {
3980         int count;
3981         print_status_struct status;
3982         WERROR result;
3983
3984         count = print_queue_length(msg_ctx, snum, &status);
3985
3986         if (servername) {
3987                 r->servername           = talloc_strdup(mem_ctx, servername);
3988                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3989         } else {
3990                 r->servername           = NULL;
3991         }
3992
3993         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3994         if (!W_ERROR_IS_OK(result)) {
3995                 return result;
3996         }
3997
3998         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3999         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4000         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4001         W_ERROR_HAVE_NO_MEMORY(r->portname);
4002         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4003         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4004
4005         if (info2->comment[0] == '\0') {
4006                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4007         } else {
4008                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4009         }
4010         W_ERROR_HAVE_NO_MEMORY(r->comment);
4011
4012         r->location             = talloc_strdup(mem_ctx, info2->location);
4013         W_ERROR_HAVE_NO_MEMORY(r->location);
4014         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4015         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4016         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4017         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4018         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4019         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4020         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4021         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4022
4023         r->attributes           = info2->attributes;
4024
4025         r->priority             = info2->priority;
4026         r->defaultpriority      = info2->defaultpriority;
4027         r->starttime            = info2->starttime;
4028         r->untiltime            = info2->untiltime;
4029         r->status               = nt_printq_status(status.status);
4030         r->cjobs                = count;
4031         r->averageppm           = info2->averageppm;
4032
4033         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4034         if (!r->devmode) {
4035                 DEBUG(8,("Returning NULL Devicemode!\n"));
4036         }
4037
4038         compose_devicemode_devicename(r->devmode, r->printername);
4039
4040         r->secdesc = NULL;
4041
4042         if (info2->secdesc != NULL) {
4043                 /* don't use talloc_steal() here unless you do a deep steal of all
4044                    the SEC_DESC members */
4045
4046                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4047         }
4048
4049         return WERR_OK;
4050 }
4051
4052 /********************************************************************
4053  * construct_printer_info3
4054  * fill a spoolss_PrinterInfo3 struct
4055  ********************************************************************/
4056
4057 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4058                                       const struct spoolss_PrinterInfo2 *info2,
4059                                       const char *servername,
4060                                       struct spoolss_PrinterInfo3 *r,
4061                                       int snum)
4062 {
4063         /* These are the components of the SD we are returning. */
4064
4065         if (info2->secdesc != NULL) {
4066                 /* don't use talloc_steal() here unless you do a deep steal of all
4067                    the SEC_DESC members */
4068
4069                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4070                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4071         }
4072
4073         return WERR_OK;
4074 }
4075
4076 /********************************************************************
4077  * construct_printer_info4
4078  * fill a spoolss_PrinterInfo4 struct
4079  ********************************************************************/
4080
4081 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4082                                       const struct spoolss_PrinterInfo2 *info2,
4083                                       const char *servername,
4084                                       struct spoolss_PrinterInfo4 *r,
4085                                       int snum)
4086 {
4087         WERROR result;
4088
4089         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4090         if (!W_ERROR_IS_OK(result)) {
4091                 return result;
4092         }
4093
4094         if (servername) {
4095                 r->servername   = talloc_strdup(mem_ctx, servername);
4096                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4097         } else {
4098                 r->servername = NULL;
4099         }
4100
4101         r->attributes   = info2->attributes;
4102
4103         return WERR_OK;
4104 }
4105
4106 /********************************************************************
4107  * construct_printer_info5
4108  * fill a spoolss_PrinterInfo5 struct
4109  ********************************************************************/
4110
4111 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4112                                       const struct spoolss_PrinterInfo2 *info2,
4113                                       const char *servername,
4114                                       struct spoolss_PrinterInfo5 *r,
4115                                       int snum)
4116 {
4117         WERROR result;
4118
4119         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4120         if (!W_ERROR_IS_OK(result)) {
4121                 return result;
4122         }
4123
4124         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4125         W_ERROR_HAVE_NO_MEMORY(r->portname);
4126
4127         r->attributes   = info2->attributes;
4128
4129         /* these two are not used by NT+ according to MSDN */
4130         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4131         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4132
4133         return WERR_OK;
4134 }
4135
4136 /********************************************************************
4137  * construct_printer_info_6
4138  * fill a spoolss_PrinterInfo6 struct
4139  ********************************************************************/
4140
4141 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4142                                       struct messaging_context *msg_ctx,
4143                                       const struct spoolss_PrinterInfo2 *info2,
4144                                       const char *servername,
4145                                       struct spoolss_PrinterInfo6 *r,
4146                                       int snum)
4147 {
4148         int count;
4149         print_status_struct status;
4150
4151         count = print_queue_length(msg_ctx, snum, &status);
4152
4153         r->status = nt_printq_status(status.status);
4154
4155         return WERR_OK;
4156 }
4157
4158 /********************************************************************
4159  * construct_printer_info7
4160  * fill a spoolss_PrinterInfo7 struct
4161  ********************************************************************/
4162
4163 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4164                                       struct messaging_context *msg_ctx,
4165                                       const char *servername,
4166                                       struct spoolss_PrinterInfo7 *r,
4167                                       int snum)
4168 {
4169         struct auth_serversupplied_info *session_info;
4170         struct GUID guid;
4171         NTSTATUS status;
4172
4173         status = make_session_info_system(mem_ctx, &session_info);
4174         if (!NT_STATUS_IS_OK(status)) {
4175                 DEBUG(0, ("construct_printer_info7: "
4176                           "Could not create system session_info\n"));
4177                 return WERR_NOMEM;
4178         }
4179
4180         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4181                                  servername,
4182                                  lp_servicename(snum), &guid, NULL)) {
4183                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4184                 r->action = DSPRINT_PUBLISH;
4185         } else {
4186                 r->guid = talloc_strdup(mem_ctx, "");
4187                 r->action = DSPRINT_UNPUBLISH;
4188         }
4189         W_ERROR_HAVE_NO_MEMORY(r->guid);
4190
4191         TALLOC_FREE(session_info);
4192         return WERR_OK;
4193 }
4194
4195 /********************************************************************
4196  * construct_printer_info8
4197  * fill a spoolss_PrinterInfo8 struct
4198  ********************************************************************/
4199
4200 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4201                                       const struct spoolss_PrinterInfo2 *info2,
4202                                       const char *servername,
4203                                       struct spoolss_DeviceModeInfo *r,
4204                                       int snum)
4205 {
4206         WERROR result;
4207         const char *printername;
4208
4209         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4210         if (!W_ERROR_IS_OK(result)) {
4211                 return result;
4212         }
4213
4214         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4215         if (!r->devmode) {
4216                 DEBUG(8,("Returning NULL Devicemode!\n"));
4217         }
4218
4219         compose_devicemode_devicename(r->devmode, printername);
4220
4221         return WERR_OK;
4222 }
4223
4224
4225 /********************************************************************
4226 ********************************************************************/
4227
4228 static bool snum_is_shared_printer(int snum)
4229 {
4230         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4231 }
4232
4233 /********************************************************************
4234  Spoolss_enumprinters.
4235 ********************************************************************/
4236
4237 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4238                                            const struct auth_serversupplied_info *session_info,
4239                                            struct messaging_context *msg_ctx,
4240                                            const char *servername,
4241                                            uint32_t level,
4242                                            uint32_t flags,
4243                                            union spoolss_PrinterInfo **info_p,
4244                                            uint32_t *count_p)
4245 {
4246         int snum;
4247         int n_services = lp_numservices();
4248         union spoolss_PrinterInfo *info = NULL;
4249         uint32_t count = 0;
4250         WERROR result = WERR_OK;
4251
4252         *count_p = 0;
4253         *info_p = NULL;
4254
4255         for (snum = 0; snum < n_services; snum++) {
4256
4257                 const char *printer;
4258                 struct spoolss_PrinterInfo2 *info2;
4259
4260                 if (!snum_is_shared_printer(snum)) {
4261                         continue;
4262                 }
4263
4264                 printer = lp_const_servicename(snum);
4265
4266                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4267                         printer, snum));
4268
4269                 result = winreg_create_printer(mem_ctx,
4270                                                session_info,
4271                                                msg_ctx,
4272                                                printer);
4273                 if (!W_ERROR_IS_OK(result)) {
4274                         goto out;
4275                 }
4276
4277                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4278                                             union spoolss_PrinterInfo,
4279                                             count + 1);
4280                 if (!info) {
4281                         result = WERR_NOMEM;
4282                         goto out;
4283                 }
4284
4285                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4286                                             printer, &info2);
4287                 if (!W_ERROR_IS_OK(result)) {
4288                         goto out;
4289                 }
4290
4291                 switch (level) {
4292                 case 0:
4293                         result = construct_printer_info0(info, session_info,
4294                                                          msg_ctx, info2,
4295                                                          servername,
4296                                                          &info[count].info0, snum);
4297                         break;
4298                 case 1:
4299                         result = construct_printer_info1(info, info2, flags,
4300                                                          servername,
4301                                                          &info[count].info1, snum);
4302                         break;
4303                 case 2:
4304                         result = construct_printer_info2(info, msg_ctx, info2,
4305                                                          servername,
4306                                                          &info[count].info2, snum);
4307                         break;
4308                 case 4:
4309                         result = construct_printer_info4(info, info2,
4310                                                          servername,
4311                                                          &info[count].info4, snum);
4312                         break;
4313                 case 5:
4314                         result = construct_printer_info5(info, info2,
4315                                                          servername,
4316                                                          &info[count].info5, snum);
4317                         break;
4318
4319                 default:
4320                         result = WERR_UNKNOWN_LEVEL;
4321                         goto out;
4322                 }
4323
4324                 if (!W_ERROR_IS_OK(result)) {
4325                         goto out;
4326                 }
4327
4328                 count++;
4329         }
4330
4331         *count_p = count;
4332         *info_p = info;
4333
4334  out:
4335         if (!W_ERROR_IS_OK(result)) {
4336                 TALLOC_FREE(info);
4337                 return result;
4338         }
4339
4340         *info_p = info;
4341
4342         return WERR_OK;
4343 }
4344
4345 /********************************************************************
4346  * handle enumeration of printers at level 0
4347  ********************************************************************/
4348
4349 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4350                                   const struct auth_serversupplied_info *session_info,
4351                                   struct messaging_context *msg_ctx,
4352                                   uint32_t flags,
4353                                   const char *servername,
4354                                   union spoolss_PrinterInfo **info,
4355                                   uint32_t *count)
4356 {
4357         DEBUG(4,("enum_all_printers_info_0\n"));
4358
4359         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4360                                             servername, 0, flags, info, count);
4361 }
4362
4363
4364 /********************************************************************
4365 ********************************************************************/
4366
4367 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4368                                        const struct auth_serversupplied_info *session_info,
4369                                        struct messaging_context *msg_ctx,
4370                                        const char *servername,
4371                                        uint32_t flags,
4372                                        union spoolss_PrinterInfo **info,
4373                                        uint32_t *count)
4374 {
4375         DEBUG(4,("enum_all_printers_info_1\n"));
4376
4377         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4378                                             servername, 1, flags, info, count);
4379 }
4380
4381 /********************************************************************
4382  enum_all_printers_info_1_local.
4383 *********************************************************************/
4384
4385 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4386                                              const struct auth_serversupplied_info *session_info,
4387                                              struct messaging_context *msg_ctx,
4388                                              const char *servername,
4389                                              union spoolss_PrinterInfo **info,
4390                                              uint32_t *count)
4391 {
4392         DEBUG(4,("enum_all_printers_info_1_local\n"));
4393
4394         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4395                                         servername, PRINTER_ENUM_ICON8, info, count);
4396 }
4397
4398 /********************************************************************
4399  enum_all_printers_info_1_name.
4400 *********************************************************************/
4401
4402 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4403                                             const struct auth_serversupplied_info *session_info,
4404                                             struct messaging_context *msg_ctx,
4405                                             const char *servername,
4406                                             union spoolss_PrinterInfo **info,
4407                                             uint32_t *count)
4408 {
4409         const char *s = servername;
4410
4411         DEBUG(4,("enum_all_printers_info_1_name\n"));
4412
4413         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4414                 s = servername + 2;
4415         }
4416
4417         if (!is_myname_or_ipaddr(s)) {
4418                 return WERR_INVALID_NAME;
4419         }
4420
4421         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4422                                         servername, PRINTER_ENUM_ICON8, info, count);
4423 }
4424
4425 /********************************************************************
4426  enum_all_printers_info_1_network.
4427 *********************************************************************/
4428
4429 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4430                                                const struct auth_serversupplied_info *session_info,
4431                                                struct messaging_context *msg_ctx,
4432                                                const char *servername,
4433                                                union spoolss_PrinterInfo **info,
4434                                                uint32_t *count)
4435 {
4436         const char *s = servername;
4437
4438         DEBUG(4,("enum_all_printers_info_1_network\n"));
4439
4440         /* If we respond to a enum_printers level 1 on our name with flags
4441            set to PRINTER_ENUM_REMOTE with a list of printers then these
4442            printers incorrectly appear in the APW browse list.
4443            Specifically the printers for the server appear at the workgroup
4444            level where all the other servers in the domain are
4445            listed. Windows responds to this call with a
4446            WERR_CAN_NOT_COMPLETE so we should do the same. */
4447
4448         if (servername[0] == '\\' && servername[1] == '\\') {
4449                  s = servername + 2;
4450         }
4451
4452         if (is_myname_or_ipaddr(s)) {
4453                  return WERR_CAN_NOT_COMPLETE;
4454         }
4455
4456         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4457                                         servername, PRINTER_ENUM_NAME, info, count);
4458 }
4459
4460 /********************************************************************
4461  * api_spoolss_enumprinters
4462  *
4463  * called from api_spoolss_enumprinters (see this to understand)
4464  ********************************************************************/
4465
4466 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4467                                        const struct auth_serversupplied_info *session_info,
4468                                        struct messaging_context *msg_ctx,
4469                                        const char *servername,
4470                                        union spoolss_PrinterInfo **info,
4471                                        uint32_t *count)
4472 {
4473         DEBUG(4,("enum_all_printers_info_2\n"));
4474
4475         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4476                                             servername, 2, 0, info, count);
4477 }
4478
4479 /********************************************************************
4480  * handle enumeration of printers at level 1
4481  ********************************************************************/
4482
4483 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4484                                   const struct auth_serversupplied_info *session_info,
4485                                   struct messaging_context *msg_ctx,
4486                                   uint32_t flags,
4487                                   const char *servername,
4488                                   union spoolss_PrinterInfo **info,
4489                                   uint32_t *count)
4490 {
4491         /* Not all the flags are equals */
4492
4493         if (flags & PRINTER_ENUM_LOCAL) {
4494                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4495                                                       msg_ctx, servername, info, count);
4496         }
4497
4498         if (flags & PRINTER_ENUM_NAME) {
4499                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4500                                                      msg_ctx, servername, info,
4501                                                      count);
4502         }
4503
4504         if (flags & PRINTER_ENUM_NETWORK) {
4505                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4506                                                         msg_ctx, servername, info,
4507                                                         count);
4508         }
4509
4510         return WERR_OK; /* NT4sp5 does that */
4511 }
4512
4513 /********************************************************************
4514  * handle enumeration of printers at level 2
4515  ********************************************************************/
4516
4517 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4518                                   const struct auth_serversupplied_info *session_info,
4519                                   struct messaging_context *msg_ctx,
4520                                   uint32_t flags,
4521                                   const char *servername,
4522                                   union spoolss_PrinterInfo **info,
4523                                   uint32_t *count)
4524 {
4525         if (flags & PRINTER_ENUM_LOCAL) {
4526
4527                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4528                                                 servername,
4529                                                 info, count);
4530         }
4531
4532         if (flags & PRINTER_ENUM_NAME) {
4533                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4534                         return WERR_INVALID_NAME;
4535                 }
4536
4537                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4538                                                 servername,
4539                                                 info, count);
4540         }
4541
4542         if (flags & PRINTER_ENUM_REMOTE) {
4543                 return WERR_UNKNOWN_LEVEL;
4544         }
4545
4546         return WERR_OK;
4547 }
4548
4549 /********************************************************************
4550  * handle enumeration of printers at level 4
4551  ********************************************************************/
4552
4553 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4554                                   const struct auth_serversupplied_info *session_info,
4555                                   struct messaging_context *msg_ctx,
4556                                   uint32_t flags,
4557                                   const char *servername,
4558                                   union spoolss_PrinterInfo **info,
4559                                   uint32_t *count)
4560 {
4561         DEBUG(4,("enum_all_printers_info_4\n"));
4562
4563         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4564                                             servername, 4, flags, info, count);
4565 }
4566
4567
4568 /********************************************************************
4569  * handle enumeration of printers at level 5
4570  ********************************************************************/
4571
4572 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4573                                   const struct auth_serversupplied_info *session_info,
4574                                   struct messaging_context *msg_ctx,
4575                                   uint32_t flags,
4576                                   const char *servername,
4577                                   union spoolss_PrinterInfo **info,
4578                                   uint32_t *count)
4579 {
4580         DEBUG(4,("enum_all_printers_info_5\n"));
4581
4582         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4583                                             servername, 5, flags, info, count);
4584 }
4585
4586 /****************************************************************
4587  _spoolss_EnumPrinters
4588 ****************************************************************/
4589
4590 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4591                              struct spoolss_EnumPrinters *r)
4592 {
4593         const struct auth_serversupplied_info *session_info = get_session_info_system();
4594         WERROR result;
4595
4596         /* that's an [in out] buffer */
4597
4598         if (!r->in.buffer && (r->in.offered != 0)) {
4599                 return WERR_INVALID_PARAM;
4600         }
4601
4602         DEBUG(4,("_spoolss_EnumPrinters\n"));
4603
4604         *r->out.needed = 0;
4605         *r->out.count = 0;
4606         *r->out.info = NULL;
4607
4608         /*
4609          * Level 1:
4610          *          flags==PRINTER_ENUM_NAME
4611          *           if name=="" then enumerates all printers
4612          *           if name!="" then enumerate the printer
4613          *          flags==PRINTER_ENUM_REMOTE
4614          *          name is NULL, enumerate printers
4615          * Level 2: name!="" enumerates printers, name can't be NULL
4616          * Level 3: doesn't exist
4617          * Level 4: does a local registry lookup
4618          * Level 5: same as Level 2
4619          */
4620
4621         if (r->in.server && r->in.server[0] == '\0') {
4622                 r->in.server = NULL;
4623         }
4624
4625         switch (r->in.level) {
4626         case 0:
4627                 result = enumprinters_level0(p->mem_ctx, session_info,
4628                                              p->msg_ctx, r->in.flags,
4629                                              r->in.server,
4630                                              r->out.info, r->out.count);
4631                 break;
4632         case 1:
4633                 result = enumprinters_level1(p->mem_ctx, session_info,
4634                                              p->msg_ctx, r->in.flags,
4635                                              r->in.server,
4636                                              r->out.info, r->out.count);
4637                 break;
4638         case 2:
4639                 result = enumprinters_level2(p->mem_ctx, session_info,
4640                                              p->msg_ctx, r->in.flags,
4641                                              r->in.server,
4642                                              r->out.info, r->out.count);
4643                 break;
4644         case 4:
4645                 result = enumprinters_level4(p->mem_ctx, session_info,
4646                                              p->msg_ctx, r->in.flags,
4647                                              r->in.server,
4648                                              r->out.info, r->out.count);
4649                 break;
4650         case 5:
4651                 result = enumprinters_level5(p->mem_ctx, session_info,
4652                                              p->msg_ctx, r->in.flags,
4653                                              r->in.server,
4654                                              r->out.info, r->out.count);
4655                 break;
4656         default:
4657                 return WERR_UNKNOWN_LEVEL;
4658         }
4659
4660         if (!W_ERROR_IS_OK(result)) {
4661                 return result;
4662         }
4663
4664         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4665                                                      spoolss_EnumPrinters,
4666                                                      *r->out.info, r->in.level,
4667                                                      *r->out.count);
4668         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4669         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4670
4671         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4672 }
4673
4674 /****************************************************************
4675  _spoolss_GetPrinter
4676 ****************************************************************/
4677
4678 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4679                            struct spoolss_GetPrinter *r)
4680 {
4681         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4682         struct spoolss_PrinterInfo2 *info2 = NULL;
4683         WERROR result = WERR_OK;
4684         int snum;
4685
4686         /* that's an [in out] buffer */
4687
4688         if (!r->in.buffer && (r->in.offered != 0)) {
4689                 return WERR_INVALID_PARAM;
4690         }
4691
4692         *r->out.needed = 0;
4693
4694         if (Printer == NULL) {
4695                 return WERR_BADFID;
4696         }
4697
4698         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4699                 return WERR_BADFID;
4700         }
4701
4702         result = winreg_get_printer(p->mem_ctx,
4703                                     get_session_info_system(),
4704                                     p->msg_ctx,
4705                                     lp_const_servicename(snum),
4706                                     &info2);
4707         if (!W_ERROR_IS_OK(result)) {
4708                 goto out;
4709         }
4710
4711         switch (r->in.level) {
4712         case 0:
4713                 result = construct_printer_info0(p->mem_ctx,
4714                                                  get_session_info_system(),
4715                                                  p->msg_ctx,
4716                                                  info2,
4717                                                  Printer->servername,
4718                                                  &r->out.info->info0,
4719                                                  snum);
4720                 break;
4721         case 1:
4722                 result = construct_printer_info1(p->mem_ctx, info2,
4723                                                  PRINTER_ENUM_ICON8,
4724                                                  Printer->servername,
4725                                                  &r->out.info->info1, snum);
4726                 break;
4727         case 2:
4728                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4729                                                  Printer->servername,
4730                                                  &r->out.info->info2, snum);
4731                 break;
4732         case 3:
4733                 result = construct_printer_info3(p->mem_ctx, info2,
4734                                                  Printer->servername,
4735                                                  &r->out.info->info3, snum);
4736                 break;
4737         case 4:
4738                 result = construct_printer_info4(p->mem_ctx, info2,
4739                                                  Printer->servername,
4740                                                  &r->out.info->info4, snum);
4741                 break;
4742         case 5:
4743                 result = construct_printer_info5(p->mem_ctx, info2,
4744                                                  Printer->servername,
4745                                                  &r->out.info->info5, snum);
4746                 break;
4747         case 6:
4748                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4749                                                  Printer->servername,
4750                                                  &r->out.info->info6, snum);
4751                 break;
4752         case 7:
4753                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4754                                                  Printer->servername,
4755                                                  &r->out.info->info7, snum);
4756                 break;
4757         case 8:
4758                 result = construct_printer_info8(p->mem_ctx, info2,
4759                                                  Printer->servername,
4760                                                  &r->out.info->info8, snum);
4761                 break;
4762         default:
4763                 result = WERR_UNKNOWN_LEVEL;
4764                 break;
4765         }
4766
4767  out:
4768         if (!W_ERROR_IS_OK(result)) {
4769                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4770                           r->in.level, win_errstr(result)));
4771                 TALLOC_FREE(r->out.info);
4772                 return result;
4773         }
4774
4775         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4776                                                r->out.info, r->in.level);
4777         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4778
4779         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4780 }
4781
4782 /********************************************************************
4783  ********************************************************************/
4784
4785 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4786         do { \
4787                 if (in && strlen(in)) { \
4788                         out = talloc_strdup(mem_ctx, in); \
4789                 } else { \
4790                         out = talloc_strdup(mem_ctx, ""); \
4791                 } \
4792                 W_ERROR_HAVE_NO_MEMORY(out); \
4793         } while (0);
4794
4795 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4796         do { \
4797                 if (in && strlen(in)) { \
4798                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4799                 } else { \
4800                         out = talloc_strdup(mem_ctx, ""); \
4801                 } \
4802                 W_ERROR_HAVE_NO_MEMORY(out); \
4803         } while (0);
4804
4805 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4806                                                   const char **string_array,
4807                                                   const char ***presult,
4808                                                   const char *cservername,
4809                                                   const char *arch,
4810                                                   int version)
4811 {
4812         int i, num_strings = 0;
4813         const char **array = NULL;
4814
4815         if (string_array == NULL) {
4816                 return WERR_INVALID_PARAMETER;
4817         }
4818
4819         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4820                 const char *str = NULL;
4821
4822                 if (cservername == NULL || arch == NULL) {
4823                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4824                 } else {
4825                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4826                 }
4827
4828                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4829                         TALLOC_FREE(array);
4830                         return WERR_NOMEM;
4831                 }
4832         }
4833
4834         if (i > 0) {
4835                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4836                              &array, &num_strings);
4837         }
4838
4839         if (presult) {
4840                 *presult = array;
4841         }
4842
4843         return WERR_OK;
4844 }
4845
4846 /********************************************************************
4847  * fill a spoolss_DriverInfo1 struct
4848  ********************************************************************/
4849
4850 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4851                                         struct spoolss_DriverInfo1 *r,
4852                                         const struct spoolss_DriverInfo8 *driver,
4853                                         const char *servername)
4854 {
4855         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4856         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4857
4858         return WERR_OK;
4859 }
4860
4861 /********************************************************************
4862  * fill a spoolss_DriverInfo2 struct
4863  ********************************************************************/
4864
4865 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4866                                         struct spoolss_DriverInfo2 *r,
4867                                         const struct spoolss_DriverInfo8 *driver,
4868                                         const char *servername)
4869
4870 {
4871         const char *cservername = canon_servername(servername);
4872
4873         r->version              = driver->version;
4874
4875         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4876         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4877         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4878         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4879
4880         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4881                                driver->architecture,
4882                                driver->version,
4883                                driver->driver_path,
4884                                r->driver_path);
4885
4886         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4887                                driver->architecture,
4888                                driver->version,
4889                                driver->data_file,
4890                                r->data_file);
4891
4892         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4893                                driver->architecture,
4894                                driver->version,
4895                                driver->config_file,
4896                                r->config_file);
4897
4898         return WERR_OK;
4899 }
4900
4901 /********************************************************************
4902  * fill a spoolss_DriverInfo3 struct
4903  ********************************************************************/
4904
4905 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4906                                         struct spoolss_DriverInfo3 *r,
4907                                         const struct spoolss_DriverInfo8 *driver,
4908                                         const char *servername)
4909 {
4910         const char *cservername = canon_servername(servername);
4911
4912         r->version              = driver->version;
4913
4914         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4915         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4916         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4917         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4918
4919         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4920                                driver->architecture,
4921                                driver->version,
4922                                driver->driver_path,
4923                                r->driver_path);
4924
4925         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4926                                driver->architecture,
4927                                driver->version,
4928                                driver->data_file,
4929                                r->data_file);
4930
4931         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4932                                driver->architecture,
4933                                driver->version,
4934                                driver->config_file,
4935                                r->config_file);
4936
4937         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4938                                driver->architecture,
4939                                driver->version,
4940                                driver->help_file,
4941                                r->help_file);
4942
4943         FILL_DRIVER_STRING(mem_ctx,
4944                            driver->monitor_name,
4945                            r->monitor_name);
4946
4947         FILL_DRIVER_STRING(mem_ctx,
4948                            driver->default_datatype,
4949                            r->default_datatype);
4950
4951         return string_array_from_driver_info(mem_ctx,
4952                                              driver->dependent_files,
4953                                              &r->dependent_files,
4954                                              cservername,
4955                                              driver->architecture,
4956                                              driver->version);
4957 }
4958
4959 /********************************************************************
4960  * fill a spoolss_DriverInfo4 struct
4961  ********************************************************************/
4962
4963 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4964                                         struct spoolss_DriverInfo4 *r,
4965                                         const struct spoolss_DriverInfo8 *driver,
4966                                         const char *servername)
4967 {
4968         const char *cservername = canon_servername(servername);
4969         WERROR result;
4970
4971         r->version              = driver->version;
4972
4973         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4974         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4975         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4976         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4977
4978         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4979                                driver->architecture,
4980                                driver->version,
4981                                driver->driver_path,
4982                                r->driver_path);
4983
4984         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4985                                driver->architecture,
4986                                driver->version,
4987                                driver->data_file,
4988                                r->data_file);
4989
4990         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4991                                driver->architecture,
4992                                driver->version,
4993                                driver->config_file,
4994                                r->config_file);
4995
4996         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4997                                driver->architecture,
4998                                driver->version,
4999                                driver->help_file,
5000                                r->help_file);
5001
5002         result = string_array_from_driver_info(mem_ctx,
5003                                                driver->dependent_files,
5004                                                &r->dependent_files,
5005                                                cservername,
5006                                                driver->architecture,
5007                                                driver->version);
5008         if (!W_ERROR_IS_OK(result)) {
5009                 return result;
5010         }
5011
5012         FILL_DRIVER_STRING(mem_ctx,
5013                            driver->monitor_name,
5014                            r->monitor_name);
5015
5016         FILL_DRIVER_STRING(mem_ctx,
5017                            driver->default_datatype,
5018                            r->default_datatype);
5019
5020
5021         result = string_array_from_driver_info(mem_ctx,
5022                                                driver->previous_names,
5023                                                &r->previous_names,
5024                                                NULL, NULL, 0);
5025
5026         return result;
5027 }
5028
5029 /********************************************************************
5030  * fill a spoolss_DriverInfo5 struct
5031  ********************************************************************/
5032
5033 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5034                                         struct spoolss_DriverInfo5 *r,
5035                                         const struct spoolss_DriverInfo8 *driver,
5036                                         const char *servername)
5037 {
5038         const char *cservername = canon_servername(servername);
5039
5040         r->version              = driver->version;
5041
5042         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5043         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5044         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5045         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5046
5047         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5048                                driver->architecture,
5049                                driver->version,
5050                                driver->driver_path,
5051                                r->driver_path);
5052
5053         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5054                                driver->architecture,
5055                                driver->version,
5056                                driver->data_file,
5057                                r->data_file);
5058
5059         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5060                                driver->architecture,
5061                                driver->version,
5062                                driver->config_file,
5063                                r->config_file);
5064
5065         r->driver_attributes    = 0;
5066         r->config_version       = 0;
5067         r->driver_version       = 0;
5068
5069         return WERR_OK;
5070 }
5071 /********************************************************************
5072  * fill a spoolss_DriverInfo6 struct
5073  ********************************************************************/
5074
5075 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5076                                         struct spoolss_DriverInfo6 *r,
5077                                         const struct spoolss_DriverInfo8 *driver,
5078                                         const char *servername)
5079 {
5080         const char *cservername = canon_servername(servername);
5081         WERROR result;
5082
5083         r->version              = driver->version;
5084
5085         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5086         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5087         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5088         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5089
5090         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5091                                driver->architecture,
5092                                driver->version,
5093                                driver->driver_path,
5094                                r->driver_path);
5095
5096         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5097                                driver->architecture,
5098                                driver->version,
5099                                driver->data_file,
5100                                r->data_file);
5101
5102         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5103                                driver->architecture,
5104                                driver->version,
5105                                driver->config_file,
5106                                r->config_file);
5107
5108         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5109                                driver->architecture,
5110                                driver->version,
5111                                driver->help_file,
5112                                r->help_file);
5113
5114         FILL_DRIVER_STRING(mem_ctx,
5115                            driver->monitor_name,
5116                            r->monitor_name);
5117
5118         FILL_DRIVER_STRING(mem_ctx,
5119                            driver->default_datatype,
5120                            r->default_datatype);
5121
5122         result = string_array_from_driver_info(mem_ctx,
5123                                                driver->dependent_files,
5124                                                &r->dependent_files,
5125                                                cservername,
5126                                                driver->architecture,
5127                                                driver->version);
5128         if (!W_ERROR_IS_OK(result)) {
5129                 return result;
5130         }
5131
5132         result = string_array_from_driver_info(mem_ctx,
5133                                                driver->previous_names,
5134                                                &r->previous_names,
5135                                                NULL, NULL, 0);
5136         if (!W_ERROR_IS_OK(result)) {
5137                 return result;
5138         }
5139
5140         r->driver_date          = driver->driver_date;
5141         r->driver_version       = driver->driver_version;
5142
5143         FILL_DRIVER_STRING(mem_ctx,
5144                            driver->manufacturer_name,
5145                            r->manufacturer_name);
5146         FILL_DRIVER_STRING(mem_ctx,
5147                            driver->manufacturer_url,
5148                            r->manufacturer_url);
5149         FILL_DRIVER_STRING(mem_ctx,
5150                            driver->hardware_id,
5151                            r->hardware_id);
5152         FILL_DRIVER_STRING(mem_ctx,
5153                            driver->provider,
5154                            r->provider);
5155
5156         return WERR_OK;
5157 }
5158
5159 /********************************************************************
5160  * fill a spoolss_DriverInfo8 struct
5161  ********************************************************************/
5162
5163 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5164                                         struct spoolss_DriverInfo8 *r,
5165                                         const struct spoolss_DriverInfo8 *driver,
5166                                         const char *servername)
5167 {
5168         const char *cservername = canon_servername(servername);
5169         WERROR result;
5170
5171         r->version              = driver->version;
5172
5173         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5174         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5175         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5176         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5177
5178         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5179                                driver->architecture,
5180                                driver->version,
5181                                driver->driver_path,
5182                                r->driver_path);
5183
5184         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5185                                driver->architecture,
5186                                driver->version,
5187                                driver->data_file,
5188                                r->data_file);
5189
5190         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5191                                driver->architecture,
5192                                driver->version,
5193                                driver->config_file,
5194                                r->config_file);
5195
5196         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5197                                driver->architecture,
5198                                driver->version,
5199                                driver->help_file,
5200                                r->help_file);
5201
5202         FILL_DRIVER_STRING(mem_ctx,
5203                            driver->monitor_name,
5204                            r->monitor_name);
5205
5206         FILL_DRIVER_STRING(mem_ctx,
5207                            driver->default_datatype,
5208                            r->default_datatype);
5209
5210         result = string_array_from_driver_info(mem_ctx,
5211                                                driver->dependent_files,
5212                                                &r->dependent_files,
5213                                                cservername,
5214                                                driver->architecture,
5215                                                driver->version);
5216         if (!W_ERROR_IS_OK(result)) {
5217                 return result;
5218         }
5219
5220         result = string_array_from_driver_info(mem_ctx,
5221                                                driver->previous_names,
5222                                                &r->previous_names,
5223                                                NULL, NULL, 0);
5224         if (!W_ERROR_IS_OK(result)) {
5225                 return result;
5226         }
5227
5228         r->driver_date          = driver->driver_date;
5229         r->driver_version       = driver->driver_version;
5230
5231         FILL_DRIVER_STRING(mem_ctx,
5232                            driver->manufacturer_name,
5233                            r->manufacturer_name);
5234         FILL_DRIVER_STRING(mem_ctx,
5235                            driver->manufacturer_url,
5236                            r->manufacturer_url);
5237         FILL_DRIVER_STRING(mem_ctx,
5238                            driver->hardware_id,
5239                            r->hardware_id);
5240         FILL_DRIVER_STRING(mem_ctx,
5241                            driver->provider,
5242                            r->provider);
5243
5244         FILL_DRIVER_STRING(mem_ctx,
5245                            driver->print_processor,
5246                            r->print_processor);
5247         FILL_DRIVER_STRING(mem_ctx,
5248                            driver->vendor_setup,
5249                            r->vendor_setup);
5250
5251         result = string_array_from_driver_info(mem_ctx,
5252                                                driver->color_profiles,
5253                                                &r->color_profiles,
5254                                                NULL, NULL, 0);
5255         if (!W_ERROR_IS_OK(result)) {
5256                 return result;
5257         }
5258
5259         FILL_DRIVER_STRING(mem_ctx,
5260                            driver->inf_path,
5261                            r->inf_path);
5262
5263         r->printer_driver_attributes    = driver->printer_driver_attributes;
5264
5265         result = string_array_from_driver_info(mem_ctx,
5266                                                driver->core_driver_dependencies,
5267                                                &r->core_driver_dependencies,
5268                                                NULL, NULL, 0);
5269         if (!W_ERROR_IS_OK(result)) {
5270                 return result;
5271         }
5272
5273         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5274         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5275
5276         return WERR_OK;
5277 }
5278
5279 #if 0 /* disabled until marshalling issues are resolved - gd */
5280 /********************************************************************
5281  ********************************************************************/
5282
5283 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5284                                           struct spoolss_DriverFileInfo *r,
5285                                           const char *cservername,
5286                                           const char *file_name,
5287                                           enum spoolss_DriverFileType file_type,
5288                                           uint32_t file_version)
5289 {
5290         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5291                                           cservername, file_name);
5292         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5293         r->file_type    = file_type;
5294         r->file_version = file_version;
5295
5296         return WERR_OK;
5297 }
5298
5299 /********************************************************************
5300  ********************************************************************/
5301
5302 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5303                                                  const struct spoolss_DriverInfo8 *driver,
5304                                                  const char *cservername,
5305                                                  struct spoolss_DriverFileInfo **info_p,
5306                                                  uint32_t *count_p)
5307 {
5308         struct spoolss_DriverFileInfo *info = NULL;
5309         uint32_t count = 0;
5310         WERROR result;
5311         uint32_t i;
5312
5313         *info_p = NULL;
5314         *count_p = 0;
5315
5316         if (strlen(driver->driver_path)) {
5317                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5318                                             struct spoolss_DriverFileInfo,
5319                                             count + 1);
5320                 W_ERROR_HAVE_NO_MEMORY(info);
5321                 result = fill_spoolss_DriverFileInfo(info,
5322                                                      &info[count],
5323                                                      cservername,
5324                                                      driver->driver_path,
5325                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5326                                                      0);
5327                 W_ERROR_NOT_OK_RETURN(result);
5328                 count++;
5329         }
5330
5331         if (strlen(driver->config_file)) {
5332                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5333                                             struct spoolss_DriverFileInfo,
5334                                             count + 1);
5335                 W_ERROR_HAVE_NO_MEMORY(info);
5336                 result = fill_spoolss_DriverFileInfo(info,
5337                                                      &info[count],
5338                                                      cservername,
5339                                                      driver->config_file,
5340                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5341                                                      0);
5342                 W_ERROR_NOT_OK_RETURN(result);
5343                 count++;
5344         }
5345
5346         if (strlen(driver->data_file)) {
5347                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5348                                             struct spoolss_DriverFileInfo,
5349                                             count + 1);
5350                 W_ERROR_HAVE_NO_MEMORY(info);
5351                 result = fill_spoolss_DriverFileInfo(info,
5352                                                      &info[count],
5353                                                      cservername,
5354                                                      driver->data_file,
5355                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5356                                                      0);
5357                 W_ERROR_NOT_OK_RETURN(result);
5358                 count++;
5359         }
5360
5361         if (strlen(driver->help_file)) {
5362                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5363                                             struct spoolss_DriverFileInfo,
5364                                             count + 1);
5365                 W_ERROR_HAVE_NO_MEMORY(info);
5366                 result = fill_spoolss_DriverFileInfo(info,
5367                                                      &info[count],
5368                                                      cservername,
5369                                                      driver->help_file,
5370                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5371                                                      0);
5372                 W_ERROR_NOT_OK_RETURN(result);
5373                 count++;
5374         }
5375
5376         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5377                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5378                                             struct spoolss_DriverFileInfo,
5379                                             count + 1);
5380                 W_ERROR_HAVE_NO_MEMORY(info);
5381                 result = fill_spoolss_DriverFileInfo(info,
5382                                                      &info[count],
5383                                                      cservername,
5384                                                      driver->dependent_files[i],
5385                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5386                                                      0);
5387                 W_ERROR_NOT_OK_RETURN(result);
5388                 count++;
5389         }
5390
5391         *info_p = info;
5392         *count_p = count;
5393
5394         return WERR_OK;
5395 }
5396
5397 /********************************************************************
5398  * fill a spoolss_DriverInfo101 struct
5399  ********************************************************************/
5400
5401 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5402                                           struct spoolss_DriverInfo101 *r,
5403                                           const struct spoolss_DriverInfo8 *driver,
5404                                           const char *servername)
5405 {
5406         const char *cservername = canon_servername(servername);
5407         WERROR result;
5408
5409         r->version              = driver->version;
5410
5411         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5412         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5413         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5414         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5415
5416         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5417                                                     cservername,
5418                                                     &r->file_info,
5419                                                     &r->file_count);
5420         if (!W_ERROR_IS_OK(result)) {
5421                 return result;
5422         }
5423
5424         FILL_DRIVER_STRING(mem_ctx,
5425                            driver->monitor_name,
5426                            r->monitor_name);
5427
5428         FILL_DRIVER_STRING(mem_ctx,
5429                            driver->default_datatype,
5430                            r->default_datatype);
5431
5432         result = string_array_from_driver_info(mem_ctx,
5433                                                driver->previous_names,
5434                                                &r->previous_names,
5435                                                NULL, NULL, 0);
5436         if (!W_ERROR_IS_OK(result)) {
5437                 return result;
5438         }
5439
5440         r->driver_date          = driver->driver_date;
5441         r->driver_version       = driver->driver_version;
5442
5443         FILL_DRIVER_STRING(mem_ctx,
5444                            driver->manufacturer_name,
5445                            r->manufacturer_name);
5446         FILL_DRIVER_STRING(mem_ctx,
5447                            driver->manufacturer_url,
5448                            r->manufacturer_url);
5449         FILL_DRIVER_STRING(mem_ctx,
5450                            driver->hardware_id,
5451                            r->hardware_id);
5452         FILL_DRIVER_STRING(mem_ctx,
5453                            driver->provider,
5454                            r->provider);
5455
5456         return WERR_OK;
5457 }
5458 #endif
5459 /********************************************************************
5460  ********************************************************************/
5461
5462 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5463                                                   const struct auth_serversupplied_info *session_info,
5464                                                   struct messaging_context *msg_ctx,
5465                                                   uint32_t level,
5466                                                   union spoolss_DriverInfo *r,
5467                                                   int snum,
5468                                                   const char *servername,
5469                                                   const char *architecture,
5470                                                   uint32_t version)
5471 {
5472         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5473         struct spoolss_DriverInfo8 *driver;
5474         WERROR result;
5475
5476         if (level == 101) {
5477                 return WERR_UNKNOWN_LEVEL;
5478         }
5479
5480         result = winreg_get_printer(mem_ctx,
5481                                     session_info,
5482                                     msg_ctx,
5483                                     lp_const_servicename(snum),
5484                                     &pinfo2);
5485
5486         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5487                 win_errstr(result)));
5488
5489         if (!W_ERROR_IS_OK(result)) {
5490                 return WERR_INVALID_PRINTER_NAME;
5491         }
5492
5493         result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5494                                    architecture,
5495                                    pinfo2->drivername, version, &driver);
5496
5497         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5498                 win_errstr(result)));
5499
5500         if (!W_ERROR_IS_OK(result)) {
5501                 /*
5502                  * Is this a W2k client ?
5503                  */
5504
5505                 if (version < 3) {
5506                         talloc_free(pinfo2);
5507                         return WERR_UNKNOWN_PRINTER_DRIVER;
5508                 }
5509
5510                 /* Yes - try again with a WinNT driver. */
5511                 version = 2;
5512                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5513                                            architecture,
5514                                            pinfo2->drivername,
5515                                            version, &driver);
5516                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5517                         win_errstr(result)));
5518                 if (!W_ERROR_IS_OK(result)) {
5519                         talloc_free(pinfo2);
5520                         return WERR_UNKNOWN_PRINTER_DRIVER;
5521                 }
5522         }
5523
5524         switch (level) {
5525         case 1:
5526                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5527                 break;
5528         case 2:
5529                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5530                 break;
5531         case 3:
5532                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5533                 break;
5534         case 4:
5535                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5536                 break;
5537         case 5:
5538                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5539                 break;
5540         case 6:
5541                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5542                 break;
5543         case 8:
5544                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5545                 break;
5546 #if 0 /* disabled until marshalling issues are resolved - gd */
5547         case 101:
5548                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5549                 break;
5550 #endif
5551         default:
5552                 result = WERR_UNKNOWN_LEVEL;
5553                 break;
5554         }
5555
5556         talloc_free(pinfo2);
5557         talloc_free(driver);
5558
5559         return result;
5560 }
5561
5562 /****************************************************************
5563  _spoolss_GetPrinterDriver2
5564 ****************************************************************/
5565
5566 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5567                                   struct spoolss_GetPrinterDriver2 *r)
5568 {
5569         struct printer_handle *printer;
5570         WERROR result;
5571
5572         int snum;
5573
5574         /* that's an [in out] buffer */
5575
5576         if (!r->in.buffer && (r->in.offered != 0)) {
5577                 return WERR_INVALID_PARAM;
5578         }
5579
5580         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5581
5582         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5583                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5584                 return WERR_INVALID_PRINTER_NAME;
5585         }
5586
5587         *r->out.needed = 0;
5588         *r->out.server_major_version = 0;
5589         *r->out.server_minor_version = 0;
5590
5591         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5592                 return WERR_BADFID;
5593         }
5594
5595         result = construct_printer_driver_info_level(p->mem_ctx,
5596                                                      get_session_info_system(),
5597                                                      p->msg_ctx,
5598                                                      r->in.level, r->out.info,
5599                                                      snum, printer->servername,
5600                                                      r->in.architecture,
5601                                                      r->in.client_major_version);
5602         if (!W_ERROR_IS_OK(result)) {
5603                 TALLOC_FREE(r->out.info);
5604                 return result;
5605         }
5606
5607         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5608                                                r->out.info, r->in.level);
5609         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5610
5611         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5612 }
5613
5614
5615 /****************************************************************
5616  _spoolss_StartPagePrinter
5617 ****************************************************************/
5618
5619 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5620                                  struct spoolss_StartPagePrinter *r)
5621 {
5622         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5623
5624         if (!Printer) {
5625                 DEBUG(3,("_spoolss_StartPagePrinter: "
5626                         "Error in startpageprinter printer handle\n"));
5627                 return WERR_BADFID;
5628         }
5629
5630         Printer->page_started = true;
5631         return WERR_OK;
5632 }
5633
5634 /****************************************************************
5635  _spoolss_EndPagePrinter
5636 ****************************************************************/
5637
5638 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5639                                struct spoolss_EndPagePrinter *r)
5640 {
5641         int snum;
5642
5643         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5644
5645         if (!Printer) {
5646                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5647                         OUR_HANDLE(r->in.handle)));
5648                 return WERR_BADFID;
5649         }
5650
5651         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5652                 return WERR_BADFID;
5653
5654         Printer->page_started = false;
5655         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5656
5657         return WERR_OK;
5658 }
5659
5660 /****************************************************************
5661  _spoolss_StartDocPrinter
5662 ****************************************************************/
5663
5664 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5665                                 struct spoolss_StartDocPrinter *r)
5666 {
5667         struct spoolss_DocumentInfo1 *info_1;
5668         int snum;
5669         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5670         WERROR werr;
5671
5672         if (!Printer) {
5673                 DEBUG(2,("_spoolss_StartDocPrinter: "
5674                         "Invalid handle (%s:%u:%u)\n",
5675                         OUR_HANDLE(r->in.handle)));
5676                 return WERR_BADFID;
5677         }
5678
5679         if (Printer->jobid) {
5680                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5681                           "StartDocPrinter called twice! "
5682                           "(existing jobid = %d)\n", Printer->jobid));
5683                 return WERR_INVALID_HANDLE;
5684         }
5685
5686         if (r->in.level != 1) {
5687                 return WERR_UNKNOWN_LEVEL;
5688         }
5689
5690         info_1 = r->in.info.info1;
5691
5692         /*
5693          * a nice thing with NT is it doesn't listen to what you tell it.
5694          * when asked to send _only_ RAW datas, it tries to send datas
5695          * in EMF format.
5696          *
5697          * So I add checks like in NT Server ...
5698          */
5699
5700         if (info_1->datatype) {
5701                 if (strcmp(info_1->datatype, "RAW") != 0) {
5702                         *r->out.job_id = 0;
5703                         return WERR_INVALID_DATATYPE;
5704                 }
5705         }
5706
5707         /* get the share number of the printer */
5708         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5709                 return WERR_BADFID;
5710         }
5711
5712         werr = print_job_start(p->session_info,
5713                                p->msg_ctx,
5714                                p->client_id->name,
5715                                snum,
5716                                info_1->document_name,
5717                                info_1->output_file,
5718                                Printer->devmode,
5719                                &Printer->jobid);
5720
5721         /* An error occured in print_job_start() so return an appropriate
5722            NT error code. */
5723
5724         if (!W_ERROR_IS_OK(werr)) {
5725                 return werr;
5726         }
5727
5728         Printer->document_started = true;
5729         *r->out.job_id = Printer->jobid;
5730
5731         return WERR_OK;
5732 }
5733
5734 /****************************************************************
5735  _spoolss_EndDocPrinter
5736 ****************************************************************/
5737
5738 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5739                               struct spoolss_EndDocPrinter *r)
5740 {
5741         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5742         NTSTATUS status;
5743         int snum;
5744
5745         if (!Printer) {
5746                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5747                         OUR_HANDLE(r->in.handle)));
5748                 return WERR_BADFID;
5749         }
5750
5751         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5752                 return WERR_BADFID;
5753         }
5754
5755         Printer->document_started = false;
5756         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5757         if (!NT_STATUS_IS_OK(status)) {
5758                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5759                           "print_job_end failed [%s]\n",
5760                           nt_errstr(status)));
5761         }
5762
5763         Printer->jobid = 0;
5764         return ntstatus_to_werror(status);
5765 }
5766
5767 /****************************************************************
5768  _spoolss_WritePrinter
5769 ****************************************************************/
5770
5771 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5772                              struct spoolss_WritePrinter *r)
5773 {
5774         ssize_t buffer_written;
5775         int snum;
5776         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5777
5778         if (!Printer) {
5779                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5780                         OUR_HANDLE(r->in.handle)));
5781                 *r->out.num_written = r->in._data_size;
5782                 return WERR_BADFID;
5783         }
5784
5785         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5786                 return WERR_BADFID;
5787
5788         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5789         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5790                                                    snum, Printer->jobid,
5791                                                    (const char *)r->in.data.data,
5792                                                    (size_t)r->in._data_size);
5793         if (buffer_written == (ssize_t)-1) {
5794                 *r->out.num_written = 0;
5795                 if (errno == ENOSPC)
5796                         return WERR_NO_SPOOL_SPACE;
5797                 else
5798                         return WERR_ACCESS_DENIED;
5799         }
5800
5801         *r->out.num_written = r->in._data_size;
5802
5803         return WERR_OK;
5804 }
5805
5806 /********************************************************************
5807  * api_spoolss_getprinter
5808  * called from the spoolss dispatcher
5809  *
5810  ********************************************************************/
5811
5812 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5813                               struct pipes_struct *p)
5814 {
5815         const struct auth_serversupplied_info *session_info = p->session_info;
5816         int snum;
5817         WERROR errcode = WERR_BADFUNC;
5818         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5819
5820         if (!Printer) {
5821                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5822                         OUR_HANDLE(handle)));
5823                 return WERR_BADFID;
5824         }
5825
5826         if (!get_printer_snum(p, handle, &snum, NULL))
5827                 return WERR_BADFID;
5828
5829         switch (command) {
5830         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5831                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5832                 break;
5833         case SPOOLSS_PRINTER_CONTROL_RESUME:
5834         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5835                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5836                 break;
5837         case SPOOLSS_PRINTER_CONTROL_PURGE:
5838                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5839                 break;
5840         default:
5841                 return WERR_UNKNOWN_LEVEL;
5842         }
5843
5844         return errcode;
5845 }
5846
5847
5848 /****************************************************************
5849  _spoolss_AbortPrinter
5850  * From MSDN: "Deletes printer's spool file if printer is configured
5851  * for spooling"
5852 ****************************************************************/
5853
5854 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5855                              struct spoolss_AbortPrinter *r)
5856 {
5857         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5858         int             snum;
5859         WERROR          errcode = WERR_OK;
5860
5861         if (!Printer) {
5862                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5863                         OUR_HANDLE(r->in.handle)));
5864                 return WERR_BADFID;
5865         }
5866
5867         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5868                 return WERR_BADFID;
5869
5870         if (!Printer->document_started) {
5871                 return WERR_SPL_NO_STARTDOC;
5872         }
5873
5874         errcode = print_job_delete(p->session_info,
5875                                    p->msg_ctx,
5876                                    snum,
5877                                    Printer->jobid);
5878
5879         return errcode;
5880 }
5881
5882 /********************************************************************
5883  * called by spoolss_api_setprinter
5884  * when updating a printer description
5885  ********************************************************************/
5886
5887 static WERROR update_printer_sec(struct policy_handle *handle,
5888                                  struct pipes_struct *p,
5889                                  struct sec_desc_buf *secdesc_ctr)
5890 {
5891         struct spoolss_security_descriptor *new_secdesc = NULL;
5892         struct spoolss_security_descriptor *old_secdesc = NULL;
5893         const char *printer;
5894         WERROR result;
5895         int snum;
5896
5897         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5898
5899         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5900                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5901                          OUR_HANDLE(handle)));
5902
5903                 result = WERR_BADFID;
5904                 goto done;
5905         }
5906
5907         if (secdesc_ctr == NULL) {
5908                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5909                 result = WERR_INVALID_PARAM;
5910                 goto done;
5911         }
5912         printer = lp_const_servicename(snum);
5913
5914         /* Check the user has permissions to change the security
5915            descriptor.  By experimentation with two NT machines, the user
5916            requires Full Access to the printer to change security
5917            information. */
5918
5919         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5920                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5921                 result = WERR_ACCESS_DENIED;
5922                 goto done;
5923         }
5924
5925         /* NT seems to like setting the security descriptor even though
5926            nothing may have actually changed. */
5927         result = winreg_get_printer_secdesc(p->mem_ctx,
5928                                             get_session_info_system(),
5929                                             p->msg_ctx,
5930                                             printer,
5931                                             &old_secdesc);
5932         if (!W_ERROR_IS_OK(result)) {
5933                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5934                 result = WERR_BADFID;
5935                 goto done;
5936         }
5937
5938         if (DEBUGLEVEL >= 10) {
5939                 struct security_acl *the_acl;
5940                 int i;
5941
5942                 the_acl = old_secdesc->dacl;
5943                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5944                            printer, the_acl->num_aces));
5945
5946                 for (i = 0; i < the_acl->num_aces; i++) {
5947                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5948                                            &the_acl->aces[i].trustee),
5949                                   the_acl->aces[i].access_mask));
5950                 }
5951
5952                 the_acl = secdesc_ctr->sd->dacl;
5953
5954                 if (the_acl) {
5955                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5956                                    printer, the_acl->num_aces));
5957
5958                         for (i = 0; i < the_acl->num_aces; i++) {
5959                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5960                                                    &the_acl->aces[i].trustee),
5961                                            the_acl->aces[i].access_mask));
5962                         }
5963                 } else {
5964                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5965                 }
5966         }
5967
5968         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5969         if (new_secdesc == NULL) {
5970                 result = WERR_NOMEM;
5971                 goto done;
5972         }
5973
5974         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5975                 result = WERR_OK;
5976                 goto done;
5977         }
5978
5979         result = winreg_set_printer_secdesc(p->mem_ctx,
5980                                             get_session_info_system(),
5981                                             p->msg_ctx,
5982                                             printer,
5983                                             new_secdesc);
5984
5985  done:
5986         return result;
5987 }
5988
5989 /********************************************************************
5990  Canonicalize printer info from a client
5991  ********************************************************************/
5992
5993 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5994                              struct spoolss_SetPrinterInfo2 *info2,
5995                              int snum)
5996 {
5997         fstring printername;
5998         const char *p;
5999
6000         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6001                 "portname=%s drivername=%s comment=%s location=%s\n",
6002                 info2->servername, info2->printername, info2->sharename,
6003                 info2->portname, info2->drivername, info2->comment,
6004                 info2->location));
6005
6006         /* we force some elements to "correct" values */
6007         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6008         if (info2->servername == NULL) {
6009                 return false;
6010         }
6011         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6012         if (info2->sharename == NULL) {
6013                 return false;
6014         }
6015
6016         /* check to see if we allow printername != sharename */
6017         if (lp_force_printername(snum)) {
6018                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6019                                         global_myname(), info2->sharename);
6020         } else {
6021                 /* make sure printername is in \\server\printername format */
6022                 fstrcpy(printername, info2->printername);
6023                 p = printername;
6024                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6025                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6026                                 p++;
6027                 }
6028
6029                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6030                                         global_myname(), p);
6031         }
6032         if (info2->printername == NULL) {
6033                 return false;
6034         }
6035
6036         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6037         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6038
6039         return true;
6040 }
6041
6042 /****************************************************************************
6043 ****************************************************************************/
6044
6045 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6046 {
6047         char *cmd = lp_addport_cmd();
6048         char *command = NULL;
6049         int ret;
6050         bool is_print_op = false;
6051
6052         if ( !*cmd ) {
6053                 return WERR_ACCESS_DENIED;
6054         }
6055
6056         command = talloc_asprintf(ctx,
6057                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6058         if (!command) {
6059                 return WERR_NOMEM;
6060         }
6061
6062         if ( token )
6063                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6064
6065         DEBUG(10,("Running [%s]\n", command));
6066
6067         /********* BEGIN SePrintOperatorPrivilege **********/
6068
6069         if ( is_print_op )
6070                 become_root();
6071
6072         ret = smbrun(command, NULL);
6073
6074         if ( is_print_op )
6075                 unbecome_root();
6076
6077         /********* END SePrintOperatorPrivilege **********/
6078
6079         DEBUGADD(10,("returned [%d]\n", ret));
6080
6081         TALLOC_FREE(command);
6082
6083         if ( ret != 0 ) {
6084                 return WERR_ACCESS_DENIED;
6085         }
6086
6087         return WERR_OK;
6088 }
6089
6090 /****************************************************************************
6091 ****************************************************************************/
6092
6093 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6094                              struct spoolss_SetPrinterInfo2 *info2,
6095                              const char *remote_machine,
6096                              struct messaging_context *msg_ctx)
6097 {
6098         char *cmd = lp_addprinter_cmd();
6099         char **qlines;
6100         char *command = NULL;
6101         int numlines;
6102         int ret;
6103         int fd;
6104         bool is_print_op = false;
6105
6106         if (!remote_machine) {
6107                 return false;
6108         }
6109
6110         command = talloc_asprintf(ctx,
6111                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6112                         cmd, info2->printername, info2->sharename,
6113                         info2->portname, info2->drivername,
6114                         info2->location, info2->comment, remote_machine);
6115         if (!command) {
6116                 return false;
6117         }
6118
6119         if ( token )
6120                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6121
6122         DEBUG(10,("Running [%s]\n", command));
6123
6124         /********* BEGIN SePrintOperatorPrivilege **********/
6125
6126         if ( is_print_op )
6127                 become_root();
6128
6129         if ( (ret = smbrun(command, &fd)) == 0 ) {
6130                 /* Tell everyone we updated smb.conf. */
6131                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6132         }
6133
6134         if ( is_print_op )
6135                 unbecome_root();
6136
6137         /********* END SePrintOperatorPrivilege **********/
6138
6139         DEBUGADD(10,("returned [%d]\n", ret));
6140
6141         TALLOC_FREE(command);
6142
6143         if ( ret != 0 ) {
6144                 if (fd != -1)
6145                         close(fd);
6146                 return false;
6147         }
6148
6149         /* reload our services immediately */
6150         become_root();
6151         reload_services(msg_ctx, -1, false);
6152         unbecome_root();
6153
6154         numlines = 0;
6155         /* Get lines and convert them back to dos-codepage */
6156         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6157         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6158         close(fd);
6159
6160         /* Set the portname to what the script says the portname should be. */
6161         /* but don't require anything to be return from the script exit a good error code */
6162
6163         if (numlines) {
6164                 /* Set the portname to what the script says the portname should be. */
6165                 info2->portname = talloc_strdup(ctx, qlines[0]);
6166                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6167         }
6168
6169         TALLOC_FREE(qlines);
6170         return true;
6171 }
6172
6173 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6174                                const struct auth_serversupplied_info *session_info,
6175                                struct messaging_context *msg_ctx,
6176                                int snum,
6177                                struct spoolss_SetPrinterInfo2 *printer,
6178                                struct spoolss_PrinterInfo2 *old_printer)
6179 {
6180         bool force_update = (old_printer == NULL);
6181         const char *dnsdomname;
6182         const char *longname;
6183         const char *uncname;
6184         const char *spooling;
6185         DATA_BLOB buffer;
6186         WERROR result = WERR_OK;
6187
6188         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6189                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6190                 winreg_set_printer_dataex(mem_ctx,
6191                                           session_info,
6192                                           msg_ctx,
6193                                           printer->sharename,
6194                                           SPOOL_DSSPOOLER_KEY,
6195                                           SPOOL_REG_DRIVERNAME,
6196                                           REG_SZ,
6197                                           buffer.data,
6198                                           buffer.length);
6199
6200                 if (!force_update) {
6201                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6202                                 printer->drivername));
6203
6204                         notify_printer_driver(server_event_context(), msg_ctx,
6205                                               snum, printer->drivername ?
6206                                               printer->drivername : "");
6207                 }
6208         }
6209
6210         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6211                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6212                 winreg_set_printer_dataex(mem_ctx,
6213                                           session_info,
6214                                           msg_ctx,
6215                                           printer->sharename,
6216                                           SPOOL_DSSPOOLER_KEY,
6217                                           SPOOL_REG_DESCRIPTION,
6218                                           REG_SZ,
6219                                           buffer.data,
6220                                           buffer.length);
6221
6222                 if (!force_update) {
6223                         notify_printer_comment(server_event_context(), msg_ctx,
6224                                                snum, printer->comment ?
6225                                                printer->comment : "");
6226                 }
6227         }
6228
6229         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6230                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6231                 winreg_set_printer_dataex(mem_ctx,
6232                                           session_info,
6233                                           msg_ctx,
6234                                           printer->sharename,
6235                                           SPOOL_DSSPOOLER_KEY,
6236                                           SPOOL_REG_PRINTSHARENAME,
6237                                           REG_SZ,
6238                                           buffer.data,
6239                                           buffer.length);
6240
6241                 if (!force_update) {
6242                         notify_printer_sharename(server_event_context(),
6243                                                  msg_ctx,
6244                                                  snum, printer->sharename ?
6245                                                  printer->sharename : "");
6246                 }
6247         }
6248
6249         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6250                 const char *p;
6251
6252                 p = strrchr(printer->printername, '\\' );
6253                 if (p != NULL) {
6254                         p++;
6255                 } else {
6256                         p = printer->printername;
6257                 }
6258
6259                 push_reg_sz(mem_ctx, &buffer, p);
6260                 winreg_set_printer_dataex(mem_ctx,
6261                                           session_info,
6262                                           msg_ctx,
6263                                           printer->sharename,
6264                                           SPOOL_DSSPOOLER_KEY,
6265                                           SPOOL_REG_PRINTERNAME,
6266                                           REG_SZ,
6267                                           buffer.data,
6268                                           buffer.length);
6269
6270                 if (!force_update) {
6271                         notify_printer_printername(server_event_context(),
6272                                                    msg_ctx, snum, p ? p : "");
6273                 }
6274         }
6275
6276         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6277                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6278                 winreg_set_printer_dataex(mem_ctx,
6279                                           session_info,
6280                                           msg_ctx,
6281                                           printer->sharename,
6282                                           SPOOL_DSSPOOLER_KEY,
6283                                           SPOOL_REG_PORTNAME,
6284                                           REG_SZ,
6285                                           buffer.data,
6286                                           buffer.length);
6287
6288                 if (!force_update) {
6289                         notify_printer_port(server_event_context(),
6290                                             msg_ctx, snum, printer->portname ?
6291                                             printer->portname : "");
6292                 }
6293         }
6294
6295         if (force_update || !strequal(printer->location, old_printer->location)) {
6296                 push_reg_sz(mem_ctx, &buffer, printer->location);
6297                 winreg_set_printer_dataex(mem_ctx,
6298                                           session_info,
6299                                           msg_ctx,
6300                                           printer->sharename,
6301                                           SPOOL_DSSPOOLER_KEY,
6302                                           SPOOL_REG_LOCATION,
6303                                           REG_SZ,
6304                                           buffer.data,
6305                                           buffer.length);
6306
6307                 if (!force_update) {
6308                         notify_printer_location(server_event_context(),
6309                                                 msg_ctx, snum,
6310                                                 printer->location ?
6311                                                 printer->location : "");
6312                 }
6313         }
6314
6315         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6316                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6317                 winreg_set_printer_dataex(mem_ctx,
6318                                           session_info,
6319                                           msg_ctx,
6320                                           printer->sharename,
6321                                           SPOOL_DSSPOOLER_KEY,
6322                                           SPOOL_REG_PRINTSEPARATORFILE,
6323                                           REG_SZ,
6324                                           buffer.data,
6325                                           buffer.length);
6326
6327                 if (!force_update) {
6328                         notify_printer_sepfile(server_event_context(),
6329                                                msg_ctx, snum,
6330                                                printer->sepfile ?
6331                                                printer->sepfile : "");
6332                 }
6333         }
6334
6335         if (force_update || printer->starttime != old_printer->starttime) {
6336                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6337                 SIVAL(buffer.data, 0, printer->starttime);
6338                 winreg_set_printer_dataex(mem_ctx,
6339                                           session_info,
6340                                           msg_ctx,
6341                                           printer->sharename,
6342                                           SPOOL_DSSPOOLER_KEY,
6343                                           SPOOL_REG_PRINTSTARTTIME,
6344                                           REG_DWORD,
6345                                           buffer.data,
6346                                           buffer.length);
6347         }
6348
6349         if (force_update || printer->untiltime != old_printer->untiltime) {
6350                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6351                 SIVAL(buffer.data, 0, printer->untiltime);
6352                 winreg_set_printer_dataex(mem_ctx,
6353                                           session_info,
6354                                           msg_ctx,
6355                                           printer->sharename,
6356                                           SPOOL_DSSPOOLER_KEY,
6357                                           SPOOL_REG_PRINTENDTIME,
6358                                           REG_DWORD,
6359                                           buffer.data,
6360                                           buffer.length);
6361         }
6362
6363         if (force_update || printer->priority != old_printer->priority) {
6364                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6365                 SIVAL(buffer.data, 0, printer->priority);
6366                 winreg_set_printer_dataex(mem_ctx,
6367                                           session_info,
6368                                           msg_ctx,
6369                                           printer->sharename,
6370                                           SPOOL_DSSPOOLER_KEY,
6371                                           SPOOL_REG_PRIORITY,
6372                                           REG_DWORD,
6373                                           buffer.data,
6374                                           buffer.length);
6375         }
6376
6377         if (force_update || printer->attributes != old_printer->attributes) {
6378                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6379                 SIVAL(buffer.data, 0, (printer->attributes &
6380                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6381                 winreg_set_printer_dataex(mem_ctx,
6382                                           session_info,
6383                                           msg_ctx,
6384                                           printer->sharename,
6385                                           SPOOL_DSSPOOLER_KEY,
6386                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6387                                           REG_DWORD,
6388                                           buffer.data,
6389                                           buffer.length);
6390
6391                 switch (printer->attributes & 0x3) {
6392                         case 0:
6393                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6394                                 break;
6395                         case 1:
6396                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6397                                 break;
6398                         case 2:
6399                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6400                                 break;
6401                         default:
6402                                 spooling = "unknown";
6403                 }
6404                 push_reg_sz(mem_ctx, &buffer, spooling);
6405                 winreg_set_printer_dataex(mem_ctx,
6406                                           session_info,
6407                                           msg_ctx,
6408                                           printer->sharename,
6409                                           SPOOL_DSSPOOLER_KEY,
6410                                           SPOOL_REG_PRINTSPOOLING,
6411                                           REG_SZ,
6412                                           buffer.data,
6413                                           buffer.length);
6414         }
6415
6416         push_reg_sz(mem_ctx, &buffer, global_myname());
6417         winreg_set_printer_dataex(mem_ctx,
6418                                   session_info,
6419                                   msg_ctx,
6420                                   printer->sharename,
6421                                   SPOOL_DSSPOOLER_KEY,
6422                                   SPOOL_REG_SHORTSERVERNAME,
6423                                   REG_SZ,
6424                                   buffer.data,
6425                                   buffer.length);
6426
6427         dnsdomname = get_mydnsfullname();
6428         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6429                 longname = talloc_strdup(mem_ctx, dnsdomname);
6430         } else {
6431                 longname = talloc_strdup(mem_ctx, global_myname());
6432         }
6433         if (longname == NULL) {
6434                 result = WERR_NOMEM;
6435                 goto done;
6436         }
6437
6438         push_reg_sz(mem_ctx, &buffer, longname);
6439         winreg_set_printer_dataex(mem_ctx,
6440                                   session_info,
6441                                   msg_ctx,
6442                                   printer->sharename,
6443                                   SPOOL_DSSPOOLER_KEY,
6444                                   SPOOL_REG_SERVERNAME,
6445                                   REG_SZ,
6446                                   buffer.data,
6447                                   buffer.length);
6448
6449         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6450                                   global_myname(), printer->sharename);
6451         push_reg_sz(mem_ctx, &buffer, uncname);
6452         winreg_set_printer_dataex(mem_ctx,
6453                                   session_info,
6454                                   msg_ctx,
6455                                   printer->sharename,
6456                                   SPOOL_DSSPOOLER_KEY,
6457                                   SPOOL_REG_UNCNAME,
6458                                   REG_SZ,
6459                                   buffer.data,
6460                                   buffer.length);
6461
6462 done:
6463         return result;
6464 }
6465
6466 /********************************************************************
6467  * Called by spoolss_api_setprinter
6468  * when updating a printer description.
6469  ********************************************************************/
6470
6471 static WERROR update_printer(struct pipes_struct *p,
6472                              struct policy_handle *handle,
6473                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6474                              struct spoolss_DeviceMode *devmode)
6475 {
6476         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6477         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6478         struct spoolss_PrinterInfo2 *old_printer;
6479         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6480         int snum;
6481         WERROR result = WERR_OK;
6482         TALLOC_CTX *tmp_ctx;
6483
6484         DEBUG(8,("update_printer\n"));
6485
6486         tmp_ctx = talloc_new(p->mem_ctx);
6487         if (tmp_ctx == NULL) {
6488                 return WERR_NOMEM;
6489         }
6490
6491         if (!Printer) {
6492                 result = WERR_BADFID;
6493                 goto done;
6494         }
6495
6496         if (!get_printer_snum(p, handle, &snum, NULL)) {
6497                 result = WERR_BADFID;
6498                 goto done;
6499         }
6500
6501         result = winreg_get_printer(tmp_ctx,
6502                                     get_session_info_system(),
6503                                     p->msg_ctx,
6504                                     lp_const_servicename(snum),
6505                                     &old_printer);
6506         if (!W_ERROR_IS_OK(result)) {
6507                 result = WERR_BADFID;
6508                 goto done;
6509         }
6510
6511         /* Do sanity check on the requested changes for Samba */
6512         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6513                 result = WERR_INVALID_PARAM;
6514                 goto done;
6515         }
6516
6517         /* FIXME!!! If the driver has changed we really should verify that
6518            it is installed before doing much else   --jerry */
6519
6520         /* Check calling user has permission to update printer description */
6521         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6522                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6523                 result = WERR_ACCESS_DENIED;
6524                 goto done;
6525         }
6526
6527         /* Call addprinter hook */
6528         /* Check changes to see if this is really needed */
6529
6530         if (*lp_addprinter_cmd() &&
6531                         (!strequal(printer->drivername, old_printer->drivername) ||
6532                          !strequal(printer->comment, old_printer->comment) ||
6533                          !strequal(printer->portname, old_printer->portname) ||
6534                          !strequal(printer->location, old_printer->location)) )
6535         {
6536                 /* add_printer_hook() will call reload_services() */
6537                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6538                                       printer, p->client_id->addr,
6539                                       p->msg_ctx)) {
6540                         result = WERR_ACCESS_DENIED;
6541                         goto done;
6542                 }
6543         }
6544
6545         update_dsspooler(tmp_ctx,
6546                          get_session_info_system(),
6547                          p->msg_ctx,
6548                          snum,
6549                          printer,
6550                          old_printer);
6551
6552         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6553
6554         if (devmode == NULL) {
6555                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6556         }
6557         result = winreg_update_printer(tmp_ctx,
6558                                        get_session_info_system(),
6559                                        p->msg_ctx,
6560                                        printer->sharename,
6561                                        printer_mask,
6562                                        printer,
6563                                        devmode,
6564                                        NULL);
6565
6566 done:
6567         talloc_free(tmp_ctx);
6568
6569         return result;
6570 }
6571
6572 /****************************************************************************
6573 ****************************************************************************/
6574 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6575                                            struct policy_handle *handle,
6576                                            struct spoolss_SetPrinterInfo7 *info7)
6577 {
6578 #ifdef HAVE_ADS
6579         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6580         WERROR result;
6581         int snum;
6582         struct printer_handle *Printer;
6583
6584         if ( lp_security() != SEC_ADS ) {
6585                 return WERR_UNKNOWN_LEVEL;
6586         }
6587
6588         Printer = find_printer_index_by_hnd(p, handle);
6589
6590         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6591
6592         if (!Printer)
6593                 return WERR_BADFID;
6594
6595         if (!get_printer_snum(p, handle, &snum, NULL))
6596                 return WERR_BADFID;
6597
6598         result = winreg_get_printer(p->mem_ctx,
6599                                     get_session_info_system(),
6600                                     p->msg_ctx,
6601                                     lp_servicename(snum),
6602                                     &pinfo2);
6603         if (!W_ERROR_IS_OK(result)) {
6604                 return WERR_BADFID;
6605         }
6606
6607         nt_printer_publish(pinfo2,
6608                            get_session_info_system(),
6609                            p->msg_ctx,
6610                            pinfo2,
6611                            info7->action);
6612
6613         TALLOC_FREE(pinfo2);
6614         return WERR_OK;
6615 #else
6616         return WERR_UNKNOWN_LEVEL;
6617 #endif
6618 }
6619
6620 /********************************************************************
6621  ********************************************************************/
6622
6623 static WERROR update_printer_devmode(struct pipes_struct *p,
6624                                      struct policy_handle *handle,
6625                                      struct spoolss_DeviceMode *devmode)
6626 {
6627         int snum;
6628         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6629         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6630
6631         DEBUG(8,("update_printer_devmode\n"));
6632
6633         if (!Printer) {
6634                 return WERR_BADFID;
6635         }
6636
6637         if (!get_printer_snum(p, handle, &snum, NULL)) {
6638                 return WERR_BADFID;
6639         }
6640
6641         /* Check calling user has permission to update printer description */
6642         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6643                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6644                 return WERR_ACCESS_DENIED;
6645         }
6646
6647         return winreg_update_printer(p->mem_ctx,
6648                                      get_session_info_system(),
6649                                      p->msg_ctx,
6650                                      lp_const_servicename(snum),
6651                                      info2_mask,
6652                                      NULL,
6653                                      devmode,
6654                                      NULL);
6655 }
6656
6657
6658 /****************************************************************
6659  _spoolss_SetPrinter
6660 ****************************************************************/
6661
6662 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6663                            struct spoolss_SetPrinter *r)
6664 {
6665         WERROR result;
6666
6667         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6668
6669         if (!Printer) {
6670                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6671                         OUR_HANDLE(r->in.handle)));
6672                 return WERR_BADFID;
6673         }
6674
6675         /* check the level */
6676         switch (r->in.info_ctr->level) {
6677                 case 0:
6678                         return control_printer(r->in.handle, r->in.command, p);
6679                 case 2:
6680                         result = update_printer(p, r->in.handle,
6681                                                 r->in.info_ctr,
6682                                                 r->in.devmode_ctr->devmode);
6683                         if (!W_ERROR_IS_OK(result))
6684                                 return result;
6685                         if (r->in.secdesc_ctr->sd)
6686                                 result = update_printer_sec(r->in.handle, p,
6687                                                             r->in.secdesc_ctr);
6688                         return result;
6689                 case 3:
6690                         return update_printer_sec(r->in.handle, p,
6691                                                   r->in.secdesc_ctr);
6692                 case 7:
6693                         return publish_or_unpublish_printer(p, r->in.handle,
6694                                                             r->in.info_ctr->info.info7);
6695                 case 8:
6696                         return update_printer_devmode(p, r->in.handle,
6697                                                       r->in.devmode_ctr->devmode);
6698                 default:
6699                         return WERR_UNKNOWN_LEVEL;
6700         }
6701 }
6702
6703 /****************************************************************
6704  _spoolss_FindClosePrinterNotify
6705 ****************************************************************/
6706
6707 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6708                                        struct spoolss_FindClosePrinterNotify *r)
6709 {
6710         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6711
6712         if (!Printer) {
6713                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6714                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6715                 return WERR_BADFID;
6716         }
6717
6718         if (Printer->notify.cli_chan != NULL &&
6719             Printer->notify.cli_chan->active_connections > 0) {
6720                 int snum = -1;
6721
6722                 if (Printer->printer_type == SPLHND_PRINTER) {
6723                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6724                                 return WERR_BADFID;
6725                         }
6726                 }
6727
6728                 srv_spoolss_replycloseprinter(snum, Printer);
6729         }
6730
6731         Printer->notify.flags=0;
6732         Printer->notify.options=0;
6733         Printer->notify.localmachine[0]='\0';
6734         Printer->notify.printerlocal=0;
6735         TALLOC_FREE(Printer->notify.option);
6736
6737         return WERR_OK;
6738 }
6739
6740 /****************************************************************
6741  _spoolss_AddJob
6742 ****************************************************************/
6743
6744 WERROR _spoolss_AddJob(struct pipes_struct *p,
6745                        struct spoolss_AddJob *r)
6746 {
6747         if (!r->in.buffer && (r->in.offered != 0)) {
6748                 return WERR_INVALID_PARAM;
6749         }
6750
6751         /* this is what a NT server returns for AddJob. AddJob must fail on
6752          * non-local printers */
6753
6754         if (r->in.level != 1) {
6755                 return WERR_UNKNOWN_LEVEL;
6756         }
6757
6758         return WERR_INVALID_PARAM;
6759 }
6760
6761 /****************************************************************************
6762 fill_job_info1
6763 ****************************************************************************/
6764
6765 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6766                              struct spoolss_JobInfo1 *r,
6767                              const print_queue_struct *queue,
6768                              int position, int snum,
6769                              struct spoolss_PrinterInfo2 *pinfo2)
6770 {
6771         struct tm *t;
6772
6773         t = gmtime(&queue->time);
6774
6775         r->job_id               = queue->job;
6776
6777         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6778         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6779         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6780         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6781         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6782         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6783         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6784         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6785         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6786         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6787         r->text_status          = talloc_strdup(mem_ctx, "");
6788         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6789
6790         r->status               = nt_printj_status(queue->status);
6791         r->priority             = queue->priority;
6792         r->position             = position;
6793         r->total_pages          = queue->page_count;
6794         r->pages_printed        = 0; /* ??? */
6795
6796         init_systemtime(&r->submitted, t);
6797
6798         return WERR_OK;
6799 }
6800
6801 /****************************************************************************
6802 fill_job_info2
6803 ****************************************************************************/
6804
6805 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6806                              struct spoolss_JobInfo2 *r,
6807                              const print_queue_struct *queue,
6808                              int position, int snum,
6809                              struct spoolss_PrinterInfo2 *pinfo2,
6810                              struct spoolss_DeviceMode *devmode)
6811 {
6812         struct tm *t;
6813
6814         t = gmtime(&queue->time);
6815
6816         r->job_id               = queue->job;
6817
6818         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6819         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6820         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6821         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6822         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6823         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6824         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6825         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6826         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6827         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6828         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6829         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6830         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6831         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6832         r->parameters           = talloc_strdup(mem_ctx, "");
6833         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6834         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6835         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6836
6837         r->devmode              = devmode;
6838
6839         r->text_status          = talloc_strdup(mem_ctx, "");
6840         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6841
6842         r->secdesc              = NULL;
6843
6844         r->status               = nt_printj_status(queue->status);
6845         r->priority             = queue->priority;
6846         r->position             = position;
6847         r->start_time           = 0;
6848         r->until_time           = 0;
6849         r->total_pages          = queue->page_count;
6850         r->size                 = queue->size;
6851         init_systemtime(&r->submitted, t);
6852         r->time                 = 0;
6853         r->pages_printed        = 0; /* ??? */
6854
6855         return WERR_OK;
6856 }
6857
6858 /****************************************************************************
6859 fill_job_info3
6860 ****************************************************************************/
6861
6862 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6863                              struct spoolss_JobInfo3 *r,
6864                              const print_queue_struct *queue,
6865                              const print_queue_struct *next_queue,
6866                              int position, int snum,
6867                              struct spoolss_PrinterInfo2 *pinfo2)
6868 {
6869         r->job_id               = queue->job;
6870         r->next_job_id          = 0;
6871         if (next_queue) {
6872                 r->next_job_id  = next_queue->job;
6873         }
6874         r->reserved             = 0;
6875
6876         return WERR_OK;
6877 }
6878
6879 /****************************************************************************
6880  Enumjobs at level 1.
6881 ****************************************************************************/
6882
6883 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6884                               const print_queue_struct *queue,
6885                               uint32_t num_queues, int snum,
6886                               struct spoolss_PrinterInfo2 *pinfo2,
6887                               union spoolss_JobInfo **info_p,
6888                               uint32_t *count)
6889 {
6890         union spoolss_JobInfo *info;
6891         int i;
6892         WERROR result = WERR_OK;
6893
6894         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6895         W_ERROR_HAVE_NO_MEMORY(info);
6896
6897         *count = num_queues;
6898
6899         for (i=0; i<*count; i++) {
6900                 result = fill_job_info1(info,
6901                                         &info[i].info1,
6902                                         &queue[i],
6903                                         i,
6904                                         snum,
6905                                         pinfo2);
6906                 if (!W_ERROR_IS_OK(result)) {
6907                         goto out;
6908                 }
6909         }
6910
6911  out:
6912         if (!W_ERROR_IS_OK(result)) {
6913                 TALLOC_FREE(info);
6914                 *count = 0;
6915                 return result;
6916         }
6917
6918         *info_p = info;
6919
6920         return WERR_OK;
6921 }
6922
6923 /****************************************************************************
6924  Enumjobs at level 2.
6925 ****************************************************************************/
6926
6927 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6928                               const print_queue_struct *queue,
6929                               uint32_t num_queues, int snum,
6930                               struct spoolss_PrinterInfo2 *pinfo2,
6931                               union spoolss_JobInfo **info_p,
6932                               uint32_t *count)
6933 {
6934         union spoolss_JobInfo *info;
6935         int i;
6936         WERROR result = WERR_OK;
6937
6938         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6939         W_ERROR_HAVE_NO_MEMORY(info);
6940
6941         *count = num_queues;
6942
6943         for (i=0; i<*count; i++) {
6944                 struct spoolss_DeviceMode *devmode;
6945
6946                 result = spoolss_create_default_devmode(info,
6947                                                         pinfo2->printername,
6948                                                         &devmode);
6949                 if (!W_ERROR_IS_OK(result)) {
6950                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6951                         goto out;
6952                 }
6953
6954                 result = fill_job_info2(info,
6955                                         &info[i].info2,
6956                                         &queue[i],
6957                                         i,
6958                                         snum,
6959                                         pinfo2,
6960                                         devmode);
6961                 if (!W_ERROR_IS_OK(result)) {
6962                         goto out;
6963                 }
6964         }
6965
6966  out:
6967         if (!W_ERROR_IS_OK(result)) {
6968                 TALLOC_FREE(info);
6969                 *count = 0;
6970                 return result;
6971         }
6972
6973         *info_p = info;
6974
6975         return WERR_OK;
6976 }
6977
6978 /****************************************************************************
6979  Enumjobs at level 3.
6980 ****************************************************************************/
6981
6982 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6983                               const print_queue_struct *queue,
6984                               uint32_t num_queues, int snum,
6985                               struct spoolss_PrinterInfo2 *pinfo2,
6986                               union spoolss_JobInfo **info_p,
6987                               uint32_t *count)
6988 {
6989         union spoolss_JobInfo *info;
6990         int i;
6991         WERROR result = WERR_OK;
6992
6993         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6994         W_ERROR_HAVE_NO_MEMORY(info);
6995
6996         *count = num_queues;
6997
6998         for (i=0; i<*count; i++) {
6999                 const print_queue_struct *next_queue = NULL;
7000
7001                 if (i+1 < *count) {
7002                         next_queue = &queue[i+1];
7003                 }
7004
7005                 result = fill_job_info3(info,
7006                                         &info[i].info3,
7007                                         &queue[i],
7008                                         next_queue,
7009                                         i,
7010                                         snum,
7011                                         pinfo2);
7012                 if (!W_ERROR_IS_OK(result)) {
7013                         goto out;
7014                 }
7015         }
7016
7017  out:
7018         if (!W_ERROR_IS_OK(result)) {
7019                 TALLOC_FREE(info);
7020                 *count = 0;
7021                 return result;
7022         }
7023
7024         *info_p = info;
7025
7026         return WERR_OK;
7027 }
7028
7029 /****************************************************************
7030  _spoolss_EnumJobs
7031 ****************************************************************/
7032
7033 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7034                          struct spoolss_EnumJobs *r)
7035 {
7036         WERROR result;
7037         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7038         int snum;
7039         print_status_struct prt_status;
7040         print_queue_struct *queue = NULL;
7041         uint32_t count;
7042
7043         /* that's an [in out] buffer */
7044
7045         if (!r->in.buffer && (r->in.offered != 0)) {
7046                 return WERR_INVALID_PARAM;
7047         }
7048
7049         DEBUG(4,("_spoolss_EnumJobs\n"));
7050
7051         *r->out.needed = 0;
7052         *r->out.count = 0;
7053         *r->out.info = NULL;
7054
7055         /* lookup the printer snum and tdb entry */
7056
7057         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7058                 return WERR_BADFID;
7059         }
7060
7061         result = winreg_get_printer(p->mem_ctx,
7062                                     get_session_info_system(),
7063                                     p->msg_ctx,
7064                                     lp_const_servicename(snum),
7065                                     &pinfo2);
7066         if (!W_ERROR_IS_OK(result)) {
7067                 return result;
7068         }
7069
7070         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7071         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7072                 count, prt_status.status, prt_status.message));
7073
7074         if (count == 0) {
7075                 SAFE_FREE(queue);
7076                 TALLOC_FREE(pinfo2);
7077                 return WERR_OK;
7078         }
7079
7080         switch (r->in.level) {
7081         case 1:
7082                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7083                                          pinfo2, r->out.info, r->out.count);
7084                 break;
7085         case 2:
7086                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7087                                          pinfo2, r->out.info, r->out.count);
7088                 break;
7089         case 3:
7090                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7091                                          pinfo2, r->out.info, r->out.count);
7092                 break;
7093         default:
7094                 result = WERR_UNKNOWN_LEVEL;
7095                 break;
7096         }
7097
7098         SAFE_FREE(queue);
7099         TALLOC_FREE(pinfo2);
7100
7101         if (!W_ERROR_IS_OK(result)) {
7102                 return result;
7103         }
7104
7105         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7106                                                      spoolss_EnumJobs,
7107                                                      *r->out.info, r->in.level,
7108                                                      *r->out.count);
7109         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7110         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7111
7112         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7113 }
7114
7115 /****************************************************************
7116  _spoolss_ScheduleJob
7117 ****************************************************************/
7118
7119 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7120                             struct spoolss_ScheduleJob *r)
7121 {
7122         return WERR_OK;
7123 }
7124
7125 /****************************************************************
7126 ****************************************************************/
7127
7128 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7129                                struct messaging_context *msg_ctx,
7130                                const char *printer_name,
7131                                uint32_t job_id,
7132                                struct spoolss_SetJobInfo1 *r)
7133 {
7134         char *old_doc_name;
7135
7136         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7137                 return WERR_BADFID;
7138         }
7139
7140         if (strequal(old_doc_name, r->document_name)) {
7141                 return WERR_OK;
7142         }
7143
7144         if (!print_job_set_name(server_event_context(), msg_ctx,
7145                                 printer_name, job_id, r->document_name)) {
7146                 return WERR_BADFID;
7147         }
7148
7149         return WERR_OK;
7150 }
7151
7152 /****************************************************************
7153  _spoolss_SetJob
7154 ****************************************************************/
7155
7156 WERROR _spoolss_SetJob(struct pipes_struct *p,
7157                        struct spoolss_SetJob *r)
7158 {
7159         const struct auth_serversupplied_info *session_info = p->session_info;
7160         int snum;
7161         WERROR errcode = WERR_BADFUNC;
7162
7163         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7164                 return WERR_BADFID;
7165         }
7166
7167         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7168                 return WERR_INVALID_PRINTER_NAME;
7169         }
7170
7171         switch (r->in.command) {
7172         case SPOOLSS_JOB_CONTROL_CANCEL:
7173         case SPOOLSS_JOB_CONTROL_DELETE:
7174                 errcode = print_job_delete(session_info, p->msg_ctx,
7175                                            snum, r->in.job_id);
7176                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7177                         errcode = WERR_OK;
7178                 }
7179                 break;
7180         case SPOOLSS_JOB_CONTROL_PAUSE:
7181                 if (print_job_pause(session_info, p->msg_ctx,
7182                                     snum, r->in.job_id, &errcode)) {
7183                         errcode = WERR_OK;
7184                 }
7185                 break;
7186         case SPOOLSS_JOB_CONTROL_RESTART:
7187         case SPOOLSS_JOB_CONTROL_RESUME:
7188                 if (print_job_resume(session_info, p->msg_ctx,
7189                                      snum, r->in.job_id, &errcode)) {
7190                         errcode = WERR_OK;
7191                 }
7192                 break;
7193         case 0:
7194                 errcode = WERR_OK;
7195                 break;
7196         default:
7197                 return WERR_UNKNOWN_LEVEL;
7198         }
7199
7200         if (!W_ERROR_IS_OK(errcode)) {
7201                 return errcode;
7202         }
7203
7204         if (r->in.ctr == NULL) {
7205                 return errcode;
7206         }
7207
7208         switch (r->in.ctr->level) {
7209         case 1:
7210                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7211                                            lp_const_servicename(snum),
7212                                            r->in.job_id,
7213                                            r->in.ctr->info.info1);
7214                 break;
7215         case 2:
7216         case 3:
7217         case 4:
7218         default:
7219                 return WERR_UNKNOWN_LEVEL;
7220         }
7221
7222         return errcode;
7223 }
7224
7225 /****************************************************************************
7226  Enumerates all printer drivers by level and architecture.
7227 ****************************************************************************/
7228
7229 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7230                                                        const struct auth_serversupplied_info *session_info,
7231                                                        struct messaging_context *msg_ctx,
7232                                                        const char *servername,
7233                                                        const char *architecture,
7234                                                        uint32_t level,
7235                                                        union spoolss_DriverInfo **info_p,
7236                                                        uint32_t *count_p)
7237 {
7238         int i;
7239         uint32_t version;
7240         struct spoolss_DriverInfo8 *driver;
7241         union spoolss_DriverInfo *info = NULL;
7242         uint32_t count = 0;
7243         WERROR result = WERR_OK;
7244         uint32_t num_drivers;
7245         const char **drivers;
7246
7247         *count_p = 0;
7248         *info_p = NULL;
7249
7250         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7251                 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7252                                                 architecture, version,
7253                                                 &num_drivers, &drivers);
7254                 if (!W_ERROR_IS_OK(result)) {
7255                         goto out;
7256                 }
7257                 DEBUG(4, ("we have:[%d] drivers in environment"
7258                           " [%s] and version [%d]\n",
7259                           num_drivers, architecture, version));
7260
7261                 if (num_drivers != 0) {
7262                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7263                                                     union spoolss_DriverInfo,
7264                                                     count + num_drivers);
7265                         if (!info) {
7266                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7267                                         "failed to enlarge driver info buffer!\n"));
7268                                 result = WERR_NOMEM;
7269                                 goto out;
7270                         }
7271                 }
7272
7273                 for (i = 0; i < num_drivers; i++) {
7274                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7275
7276                         result = winreg_get_driver(mem_ctx, session_info,
7277                                                    msg_ctx,
7278                                                    architecture, drivers[i],
7279                                                    version, &driver);
7280                         if (!W_ERROR_IS_OK(result)) {
7281                                 goto out;
7282                         }
7283
7284                         switch (level) {
7285                         case 1:
7286                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7287                                                                    driver, servername);
7288                                 break;
7289                         case 2:
7290                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7291                                                                    driver, servername);
7292                                 break;
7293                         case 3:
7294                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7295                                                                    driver, servername);
7296                                 break;
7297                         case 4:
7298                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7299                                                                    driver, servername);
7300                                 break;
7301                         case 5:
7302                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7303                                                                    driver, servername);
7304                                 break;
7305                         case 6:
7306                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7307                                                                    driver, servername);
7308                                 break;
7309                         case 8:
7310                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7311                                                                    driver, servername);
7312                                 break;
7313                         default:
7314                                 result = WERR_UNKNOWN_LEVEL;
7315                                 break;
7316                         }
7317
7318                         TALLOC_FREE(driver);
7319
7320                         if (!W_ERROR_IS_OK(result)) {
7321                                 goto out;
7322                         }
7323                 }
7324
7325                 count += num_drivers;
7326                 TALLOC_FREE(drivers);
7327         }
7328
7329  out:
7330         TALLOC_FREE(drivers);
7331
7332         if (!W_ERROR_IS_OK(result)) {
7333                 TALLOC_FREE(info);
7334                 return result;
7335         }
7336
7337         *info_p = info;
7338         *count_p = count;
7339
7340         return WERR_OK;
7341 }
7342
7343 /****************************************************************************
7344  Enumerates all printer drivers by level.
7345 ****************************************************************************/
7346
7347 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7348                                        const struct auth_serversupplied_info *session_info,
7349                                        struct messaging_context *msg_ctx,
7350                                        const char *servername,
7351                                        const char *architecture,
7352                                        uint32_t level,
7353                                        union spoolss_DriverInfo **info_p,
7354                                        uint32_t *count_p)
7355 {
7356         uint32_t a,i;
7357         WERROR result = WERR_OK;
7358
7359         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7360
7361                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7362
7363                         union spoolss_DriverInfo *info = NULL;
7364                         uint32_t count = 0;
7365
7366                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7367                                                                           session_info,
7368                                                                           msg_ctx,
7369                                                                           servername,
7370                                                                           archi_table[a].long_archi,
7371                                                                           level,
7372                                                                           &info,
7373                                                                           &count);
7374                         if (!W_ERROR_IS_OK(result)) {
7375                                 continue;
7376                         }
7377
7378                         for (i=0; i < count; i++) {
7379                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7380                                              info[i], info_p, count_p);
7381                         }
7382                 }
7383
7384                 return result;
7385         }
7386
7387         return enumprinterdrivers_level_by_architecture(mem_ctx,
7388                                                         session_info,
7389                                                         msg_ctx,
7390                                                         servername,
7391                                                         architecture,
7392                                                         level,
7393                                                         info_p,
7394                                                         count_p);
7395 }
7396
7397 /****************************************************************
7398  _spoolss_EnumPrinterDrivers
7399 ****************************************************************/
7400
7401 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7402                                    struct spoolss_EnumPrinterDrivers *r)
7403 {
7404         const char *cservername;
7405         WERROR result;
7406
7407         /* that's an [in out] buffer */
7408
7409         if (!r->in.buffer && (r->in.offered != 0)) {
7410                 return WERR_INVALID_PARAM;
7411         }
7412
7413         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7414
7415         *r->out.needed = 0;
7416         *r->out.count = 0;
7417         *r->out.info = NULL;
7418
7419         cservername = canon_servername(r->in.server);
7420
7421         if (!is_myname_or_ipaddr(cservername)) {
7422                 return WERR_UNKNOWN_PRINTER_DRIVER;
7423         }
7424
7425         result = enumprinterdrivers_level(p->mem_ctx,
7426                                           get_session_info_system(),
7427                                           p->msg_ctx,
7428                                           cservername,
7429                                           r->in.environment,
7430                                           r->in.level,
7431                                           r->out.info,
7432                                           r->out.count);
7433         if (!W_ERROR_IS_OK(result)) {
7434                 return result;
7435         }
7436
7437         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7438                                                      spoolss_EnumPrinterDrivers,
7439                                                      *r->out.info, r->in.level,
7440                                                      *r->out.count);
7441         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7442         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7443
7444         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7445 }
7446
7447 /****************************************************************
7448  _spoolss_EnumForms
7449 ****************************************************************/
7450
7451 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7452                           struct spoolss_EnumForms *r)
7453 {
7454         WERROR result;
7455
7456         *r->out.count = 0;
7457         *r->out.needed = 0;
7458         *r->out.info = NULL;
7459
7460         /* that's an [in out] buffer */
7461
7462         if (!r->in.buffer && (r->in.offered != 0) ) {
7463                 return WERR_INVALID_PARAM;
7464         }
7465
7466         DEBUG(4,("_spoolss_EnumForms\n"));
7467         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7468         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7469
7470         switch (r->in.level) {
7471         case 1:
7472                 result = winreg_printer_enumforms1(p->mem_ctx,
7473                                                    get_session_info_system(),
7474                                                    p->msg_ctx,
7475                                                    r->out.count,
7476                                                    r->out.info);
7477                 break;
7478         default:
7479                 result = WERR_UNKNOWN_LEVEL;
7480                 break;
7481         }
7482
7483         if (!W_ERROR_IS_OK(result)) {
7484                 return result;
7485         }
7486
7487         if (*r->out.count == 0) {
7488                 return WERR_NO_MORE_ITEMS;
7489         }
7490
7491         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7492                                                      spoolss_EnumForms,
7493                                                      *r->out.info, r->in.level,
7494                                                      *r->out.count);
7495         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7496         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7497
7498         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7499 }
7500
7501 /****************************************************************
7502  _spoolss_GetForm
7503 ****************************************************************/
7504
7505 WERROR _spoolss_GetForm(struct pipes_struct *p,
7506                         struct spoolss_GetForm *r)
7507 {
7508         WERROR result;
7509
7510         /* that's an [in out] buffer */
7511
7512         if (!r->in.buffer && (r->in.offered != 0)) {
7513                 return WERR_INVALID_PARAM;
7514         }
7515
7516         DEBUG(4,("_spoolss_GetForm\n"));
7517         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7518         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7519
7520         switch (r->in.level) {
7521         case 1:
7522                 result = winreg_printer_getform1(p->mem_ctx,
7523                                                  get_session_info_system(),
7524                                                  p->msg_ctx,
7525                                                  r->in.form_name,
7526                                                  &r->out.info->info1);
7527                 break;
7528         default:
7529                 result = WERR_UNKNOWN_LEVEL;
7530                 break;
7531         }
7532
7533         if (!W_ERROR_IS_OK(result)) {
7534                 TALLOC_FREE(r->out.info);
7535                 return result;
7536         }
7537
7538         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7539                                                r->out.info, r->in.level);
7540         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7541
7542         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7543 }
7544
7545 /****************************************************************************
7546 ****************************************************************************/
7547
7548 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7549                           struct spoolss_PortInfo1 *r,
7550                           const char *name)
7551 {
7552         r->port_name = talloc_strdup(mem_ctx, name);
7553         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7554
7555         return WERR_OK;
7556 }
7557
7558 /****************************************************************************
7559  TODO: This probably needs distinguish between TCP/IP and Local ports
7560  somehow.
7561 ****************************************************************************/
7562
7563 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7564                           struct spoolss_PortInfo2 *r,
7565                           const char *name)
7566 {
7567         r->port_name = talloc_strdup(mem_ctx, name);
7568         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7569
7570         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7571         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7572
7573         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7574         W_ERROR_HAVE_NO_MEMORY(r->description);
7575
7576         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7577         r->reserved = 0;
7578
7579         return WERR_OK;
7580 }
7581
7582
7583 /****************************************************************************
7584  wrapper around the enumer ports command
7585 ****************************************************************************/
7586
7587 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7588 {
7589         char *cmd = lp_enumports_cmd();
7590         char **qlines = NULL;
7591         char *command = NULL;
7592         int numlines;
7593         int ret;
7594         int fd;
7595
7596         *count = 0;
7597         *lines = NULL;
7598
7599         /* if no hook then just fill in the default port */
7600
7601         if ( !*cmd ) {
7602                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7603                         return WERR_NOMEM;
7604                 }
7605                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7606                         TALLOC_FREE(qlines);
7607                         return WERR_NOMEM;
7608                 }
7609                 qlines[1] = NULL;
7610                 numlines = 1;
7611         }
7612         else {
7613                 /* we have a valid enumport command */
7614
7615                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7616                 if (!command) {
7617                         return WERR_NOMEM;
7618                 }
7619
7620                 DEBUG(10,("Running [%s]\n", command));
7621                 ret = smbrun(command, &fd);
7622                 DEBUG(10,("Returned [%d]\n", ret));
7623                 TALLOC_FREE(command);
7624                 if (ret != 0) {
7625                         if (fd != -1) {
7626                                 close(fd);
7627                         }
7628                         return WERR_ACCESS_DENIED;
7629                 }
7630
7631                 numlines = 0;
7632                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7633                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7634                 close(fd);
7635         }
7636
7637         *count = numlines;
7638         *lines = qlines;
7639
7640         return WERR_OK;
7641 }
7642
7643 /****************************************************************************
7644  enumports level 1.
7645 ****************************************************************************/
7646
7647 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7648                                 union spoolss_PortInfo **info_p,
7649                                 uint32_t *count)
7650 {
7651         union spoolss_PortInfo *info = NULL;
7652         int i=0;
7653         WERROR result = WERR_OK;
7654         char **qlines = NULL;
7655         int numlines = 0;
7656
7657         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7658         if (!W_ERROR_IS_OK(result)) {
7659                 goto out;
7660         }
7661
7662         if (numlines) {
7663                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7664                 if (!info) {
7665                         DEBUG(10,("Returning WERR_NOMEM\n"));
7666                         result = WERR_NOMEM;
7667                         goto out;
7668                 }
7669
7670                 for (i=0; i<numlines; i++) {
7671                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7672                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7673                         if (!W_ERROR_IS_OK(result)) {
7674                                 goto out;
7675                         }
7676                 }
7677         }
7678         TALLOC_FREE(qlines);
7679
7680 out:
7681         if (!W_ERROR_IS_OK(result)) {
7682                 TALLOC_FREE(info);
7683                 TALLOC_FREE(qlines);
7684                 *count = 0;
7685                 *info_p = NULL;
7686                 return result;
7687         }
7688
7689         *info_p = info;
7690         *count = numlines;
7691
7692         return WERR_OK;
7693 }
7694
7695 /****************************************************************************
7696  enumports level 2.
7697 ****************************************************************************/
7698
7699 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7700                                 union spoolss_PortInfo **info_p,
7701                                 uint32_t *count)
7702 {
7703         union spoolss_PortInfo *info = NULL;
7704         int i=0;
7705         WERROR result = WERR_OK;
7706         char **qlines = NULL;
7707         int numlines = 0;
7708
7709         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7710         if (!W_ERROR_IS_OK(result)) {
7711                 goto out;
7712         }
7713
7714         if (numlines) {
7715                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7716                 if (!info) {
7717                         DEBUG(10,("Returning WERR_NOMEM\n"));
7718                         result = WERR_NOMEM;
7719                         goto out;
7720                 }
7721
7722                 for (i=0; i<numlines; i++) {
7723                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7724                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7725                         if (!W_ERROR_IS_OK(result)) {
7726                                 goto out;
7727                         }
7728                 }
7729         }
7730         TALLOC_FREE(qlines);
7731
7732 out:
7733         if (!W_ERROR_IS_OK(result)) {
7734                 TALLOC_FREE(info);
7735                 TALLOC_FREE(qlines);
7736                 *count = 0;
7737                 *info_p = NULL;
7738                 return result;
7739         }
7740
7741         *info_p = info;
7742         *count = numlines;
7743
7744         return WERR_OK;
7745 }
7746
7747 /****************************************************************
7748  _spoolss_EnumPorts
7749 ****************************************************************/
7750
7751 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7752                           struct spoolss_EnumPorts *r)
7753 {
7754         WERROR result;
7755
7756         /* that's an [in out] buffer */
7757
7758         if (!r->in.buffer && (r->in.offered != 0)) {
7759                 return WERR_INVALID_PARAM;
7760         }
7761
7762         DEBUG(4,("_spoolss_EnumPorts\n"));
7763
7764         *r->out.count = 0;
7765         *r->out.needed = 0;
7766         *r->out.info = NULL;
7767
7768         switch (r->in.level) {
7769         case 1:
7770                 result = enumports_level_1(p->mem_ctx, r->out.info,
7771                                            r->out.count);
7772                 break;
7773         case 2:
7774                 result = enumports_level_2(p->mem_ctx, r->out.info,
7775                                            r->out.count);
7776                 break;
7777         default:
7778                 return WERR_UNKNOWN_LEVEL;
7779         }
7780
7781         if (!W_ERROR_IS_OK(result)) {
7782                 return result;
7783         }
7784
7785         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7786                                                      spoolss_EnumPorts,
7787                                                      *r->out.info, r->in.level,
7788                                                      *r->out.count);
7789         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7790         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7791
7792         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7793 }
7794
7795 /****************************************************************************
7796 ****************************************************************************/
7797
7798 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7799                                            const char *server,
7800                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7801                                            struct spoolss_DeviceMode *devmode,
7802                                            struct security_descriptor *secdesc,
7803                                            struct spoolss_UserLevelCtr *user_ctr,
7804                                            struct policy_handle *handle)
7805 {
7806         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7807         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7808         int     snum;
7809         WERROR err = WERR_OK;
7810
7811         /* samba does not have a concept of local, non-shared printers yet, so
7812          * make sure we always setup sharename - gd */
7813         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7814             (info2->printername != NULL && info2->printername[0] != '\0')) {
7815                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7816                         "no sharename has been set, setting printername %s as sharename\n",
7817                         info2->printername));
7818                 info2->sharename = info2->printername;
7819         }
7820
7821         /* check to see if the printer already exists */
7822         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7823                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7824                         info2->sharename));
7825                 return WERR_PRINTER_ALREADY_EXISTS;
7826         }
7827
7828         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7829                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7830                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7831                                 info2->printername));
7832                         return WERR_PRINTER_ALREADY_EXISTS;
7833                 }
7834         }
7835
7836         /* validate printer info struct */
7837         if (!info2->printername || strlen(info2->printername) == 0) {
7838                 return WERR_INVALID_PRINTER_NAME;
7839         }
7840         if (!info2->portname || strlen(info2->portname) == 0) {
7841                 return WERR_UNKNOWN_PORT;
7842         }
7843         if (!info2->drivername || strlen(info2->drivername) == 0) {
7844                 return WERR_UNKNOWN_PRINTER_DRIVER;
7845         }
7846         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7847                 return WERR_UNKNOWN_PRINTPROCESSOR;
7848         }
7849
7850         /* FIXME!!!  smbd should check to see if the driver is installed before
7851            trying to add a printer like this  --jerry */
7852
7853         if (*lp_addprinter_cmd() ) {
7854                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7855                                        info2, p->client_id->addr,
7856                                        p->msg_ctx) ) {
7857                         return WERR_ACCESS_DENIED;
7858                 }
7859         } else {
7860                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7861                         "smb.conf parameter \"addprinter command\" is defined. This"
7862                         "parameter must exist for this call to succeed\n",
7863                         info2->sharename ));
7864         }
7865
7866         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7867                 return WERR_ACCESS_DENIED;
7868         }
7869
7870         /* you must be a printer admin to add a new printer */
7871         if (!print_access_check(p->session_info,
7872                                 p->msg_ctx,
7873                                 snum,
7874                                 PRINTER_ACCESS_ADMINISTER)) {
7875                 return WERR_ACCESS_DENIED;
7876         }
7877
7878         /*
7879          * Do sanity check on the requested changes for Samba.
7880          */
7881
7882         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7883                 return WERR_INVALID_PARAM;
7884         }
7885
7886         if (devmode == NULL) {
7887                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7888         }
7889
7890         update_dsspooler(p->mem_ctx,
7891                          get_session_info_system(),
7892                          p->msg_ctx,
7893                          0,
7894                          info2,
7895                          NULL);
7896
7897         err = winreg_update_printer(p->mem_ctx,
7898                                     get_session_info_system(),
7899                                     p->msg_ctx,
7900                                     info2->sharename,
7901                                     info2_mask,
7902                                     info2,
7903                                     devmode,
7904                                     secdesc);
7905         if (!W_ERROR_IS_OK(err)) {
7906                 return err;
7907         }
7908
7909         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7910         if (!W_ERROR_IS_OK(err)) {
7911                 /* Handle open failed - remove addition. */
7912                 ZERO_STRUCTP(handle);
7913                 return err;
7914         }
7915
7916         return WERR_OK;
7917 }
7918
7919 /****************************************************************
7920  _spoolss_AddPrinterEx
7921 ****************************************************************/
7922
7923 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7924                              struct spoolss_AddPrinterEx *r)
7925 {
7926         switch (r->in.info_ctr->level) {
7927         case 1:
7928                 /* we don't handle yet */
7929                 /* but I know what to do ... */
7930                 return WERR_UNKNOWN_LEVEL;
7931         case 2:
7932                 return spoolss_addprinterex_level_2(p, r->in.server,
7933                                                     r->in.info_ctr,
7934                                                     r->in.devmode_ctr->devmode,
7935                                                     r->in.secdesc_ctr->sd,
7936                                                     r->in.userlevel_ctr,
7937                                                     r->out.handle);
7938         default:
7939                 return WERR_UNKNOWN_LEVEL;
7940         }
7941 }
7942
7943 /****************************************************************
7944  _spoolss_AddPrinter
7945 ****************************************************************/
7946
7947 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7948                            struct spoolss_AddPrinter *r)
7949 {
7950         struct spoolss_AddPrinterEx a;
7951         struct spoolss_UserLevelCtr userlevel_ctr;
7952
7953         ZERO_STRUCT(userlevel_ctr);
7954
7955         userlevel_ctr.level = 1;
7956
7957         a.in.server             = r->in.server;
7958         a.in.info_ctr           = r->in.info_ctr;
7959         a.in.devmode_ctr        = r->in.devmode_ctr;
7960         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7961         a.in.userlevel_ctr      = &userlevel_ctr;
7962         a.out.handle            = r->out.handle;
7963
7964         return _spoolss_AddPrinterEx(p, &a);
7965 }
7966
7967 /****************************************************************
7968  _spoolss_AddPrinterDriverEx
7969 ****************************************************************/
7970
7971 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7972                                    struct spoolss_AddPrinterDriverEx *r)
7973 {
7974         WERROR err = WERR_OK;
7975         const char *driver_name = NULL;
7976         uint32_t version;
7977         const char *fn;
7978
7979         switch (p->opnum) {
7980                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7981                         fn = "_spoolss_AddPrinterDriver";
7982                         break;
7983                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7984                         fn = "_spoolss_AddPrinterDriverEx";
7985                         break;
7986                 default:
7987                         return WERR_INVALID_PARAM;
7988         }
7989
7990         /*
7991          * we only support the semantics of AddPrinterDriver()
7992          * i.e. only copy files that are newer than existing ones
7993          */
7994
7995         if (r->in.flags == 0) {
7996                 return WERR_INVALID_PARAM;
7997         }
7998
7999         if (r->in.flags != APD_COPY_NEW_FILES) {
8000                 return WERR_ACCESS_DENIED;
8001         }
8002
8003         /* FIXME */
8004         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8005                 /* Clever hack from Martin Zielinski <mz@seh.de>
8006                  * to allow downgrade from level 8 (Vista).
8007                  */
8008                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8009                         r->in.info_ctr->level));
8010                 return WERR_UNKNOWN_LEVEL;
8011         }
8012
8013         DEBUG(5,("Cleaning driver's information\n"));
8014         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8015         if (!W_ERROR_IS_OK(err))
8016                 goto done;
8017
8018         DEBUG(5,("Moving driver to final destination\n"));
8019         err = move_driver_to_download_area(p, r->in.info_ctr);
8020         if (!W_ERROR_IS_OK(err)) {
8021                 goto done;
8022         }
8023
8024         err = winreg_add_driver(p->mem_ctx,
8025                                 get_session_info_system(),
8026                                 p->msg_ctx,
8027                                 r->in.info_ctr,
8028                                 &driver_name,
8029                                 &version);
8030         if (!W_ERROR_IS_OK(err)) {
8031                 goto done;
8032         }
8033
8034         /*
8035          * I think this is where he DrvUpgradePrinter() hook would be
8036          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8037          * server.  Right now, we just need to send ourselves a message
8038          * to update each printer bound to this driver.   --jerry
8039          */
8040
8041         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8042                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8043                         fn, driver_name));
8044         }
8045
8046 done:
8047         return err;
8048 }
8049
8050 /****************************************************************
8051  _spoolss_AddPrinterDriver
8052 ****************************************************************/
8053
8054 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8055                                  struct spoolss_AddPrinterDriver *r)
8056 {
8057         struct spoolss_AddPrinterDriverEx a;
8058
8059         switch (r->in.info_ctr->level) {
8060         case 2:
8061         case 3:
8062         case 4:
8063         case 5:
8064                 break;
8065         default:
8066                 return WERR_UNKNOWN_LEVEL;
8067         }
8068
8069         a.in.servername         = r->in.servername;
8070         a.in.info_ctr           = r->in.info_ctr;
8071         a.in.flags              = APD_COPY_NEW_FILES;
8072
8073         return _spoolss_AddPrinterDriverEx(p, &a);
8074 }
8075
8076 /****************************************************************************
8077 ****************************************************************************/
8078
8079 struct _spoolss_paths {
8080         int type;
8081         const char *share;
8082         const char *dir;
8083 };
8084
8085 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8086
8087 static const struct _spoolss_paths spoolss_paths[]= {
8088         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8089         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8090 };
8091
8092 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8093                                           const char *servername,
8094                                           const char *environment,
8095                                           int component,
8096                                           char **path)
8097 {
8098         const char *pservername = NULL;
8099         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8100         const char *short_archi;
8101
8102         *path = NULL;
8103
8104         /* environment may be empty */
8105         if (environment && strlen(environment)) {
8106                 long_archi = environment;
8107         }
8108
8109         /* servername may be empty */
8110         if (servername && strlen(servername)) {
8111                 pservername = canon_servername(servername);
8112
8113                 if (!is_myname_or_ipaddr(pservername)) {
8114                         return WERR_INVALID_PARAM;
8115                 }
8116         }
8117
8118         if (!(short_archi = get_short_archi(long_archi))) {
8119                 return WERR_INVALID_ENVIRONMENT;
8120         }
8121
8122         switch (component) {
8123         case SPOOLSS_PRTPROCS_PATH:
8124         case SPOOLSS_DRIVER_PATH:
8125                 if (pservername) {
8126                         *path = talloc_asprintf(mem_ctx,
8127                                         "\\\\%s\\%s\\%s",
8128                                         pservername,
8129                                         spoolss_paths[component].share,
8130                                         short_archi);
8131                 } else {
8132                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8133                                         SPOOLSS_DEFAULT_SERVER_PATH,
8134                                         spoolss_paths[component].dir,
8135                                         short_archi);
8136                 }
8137                 break;
8138         default:
8139                 return WERR_INVALID_PARAM;
8140         }
8141
8142         if (!*path) {
8143                 return WERR_NOMEM;
8144         }
8145
8146         return WERR_OK;
8147 }
8148
8149 /****************************************************************************
8150 ****************************************************************************/
8151
8152 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8153                                           const char *servername,
8154                                           const char *environment,
8155                                           struct spoolss_DriverDirectoryInfo1 *r)
8156 {
8157         WERROR werr;
8158         char *path = NULL;
8159
8160         werr = compose_spoolss_server_path(mem_ctx,
8161                                            servername,
8162                                            environment,
8163                                            SPOOLSS_DRIVER_PATH,
8164                                            &path);
8165         if (!W_ERROR_IS_OK(werr)) {
8166                 return werr;
8167         }
8168
8169         DEBUG(4,("printer driver directory: [%s]\n", path));
8170
8171         r->directory_name = path;
8172
8173         return WERR_OK;
8174 }
8175
8176 /****************************************************************
8177  _spoolss_GetPrinterDriverDirectory
8178 ****************************************************************/
8179
8180 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8181                                           struct spoolss_GetPrinterDriverDirectory *r)
8182 {
8183         WERROR werror;
8184
8185         /* that's an [in out] buffer */
8186
8187         if (!r->in.buffer && (r->in.offered != 0)) {
8188                 return WERR_INVALID_PARAM;
8189         }
8190
8191         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8192                 r->in.level));
8193
8194         *r->out.needed = 0;
8195
8196         /* r->in.level is ignored */
8197
8198         werror = getprinterdriverdir_level_1(p->mem_ctx,
8199                                              r->in.server,
8200                                              r->in.environment,
8201                                              &r->out.info->info1);
8202         if (!W_ERROR_IS_OK(werror)) {
8203                 TALLOC_FREE(r->out.info);
8204                 return werror;
8205         }
8206
8207         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8208                                                r->out.info, r->in.level);
8209         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8210
8211         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8212 }
8213
8214 /****************************************************************
8215  _spoolss_EnumPrinterData
8216 ****************************************************************/
8217
8218 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8219                                 struct spoolss_EnumPrinterData *r)
8220 {
8221         WERROR result;
8222         struct spoolss_EnumPrinterDataEx r2;
8223         uint32_t count;
8224         struct spoolss_PrinterEnumValues *info, *val = NULL;
8225         uint32_t needed;
8226
8227         r2.in.handle    = r->in.handle;
8228         r2.in.key_name  = "PrinterDriverData";
8229         r2.in.offered   = 0;
8230         r2.out.count    = &count;
8231         r2.out.info     = &info;
8232         r2.out.needed   = &needed;
8233
8234         result = _spoolss_EnumPrinterDataEx(p, &r2);
8235         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8236                 r2.in.offered = needed;
8237                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8238         }
8239         if (!W_ERROR_IS_OK(result)) {
8240                 return result;
8241         }
8242
8243         /*
8244          * The NT machine wants to know the biggest size of value and data
8245          *
8246          * cf: MSDN EnumPrinterData remark section
8247          */
8248
8249         if (!r->in.value_offered && !r->in.data_offered) {
8250                 uint32_t biggest_valuesize = 0;
8251                 uint32_t biggest_datasize = 0;
8252                 int i, name_length;
8253
8254                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8255
8256                 for (i=0; i<count; i++) {
8257
8258                         name_length = strlen(info[i].value_name);
8259                         if (strlen(info[i].value_name) > biggest_valuesize) {
8260                                 biggest_valuesize = name_length;
8261                         }
8262
8263                         if (info[i].data_length > biggest_datasize) {
8264                                 biggest_datasize = info[i].data_length;
8265                         }
8266
8267                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8268                                 biggest_datasize));
8269                 }
8270
8271                 /* the value is an UNICODE string but real_value_size is the length
8272                    in bytes including the trailing 0 */
8273
8274                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8275                 *r->out.data_needed  = biggest_datasize;
8276
8277                 DEBUG(6,("final values: [%d], [%d]\n",
8278                         *r->out.value_needed, *r->out.data_needed));
8279
8280                 return WERR_OK;
8281         }
8282
8283         if (r->in.enum_index < count) {
8284                 val = &info[r->in.enum_index];
8285         }
8286
8287         if (val == NULL) {
8288                 /* out_value should default to "" or else NT4 has
8289                    problems unmarshalling the response */
8290
8291                 if (r->in.value_offered) {
8292                         *r->out.value_needed = 1;
8293                         r->out.value_name = talloc_strdup(r, "");
8294                         if (!r->out.value_name) {
8295                                 return WERR_NOMEM;
8296                         }
8297                 } else {
8298                         r->out.value_name = NULL;
8299                         *r->out.value_needed = 0;
8300                 }
8301
8302                 /* the data is counted in bytes */
8303
8304                 *r->out.data_needed = r->in.data_offered;
8305
8306                 result = WERR_NO_MORE_ITEMS;
8307         } else {
8308                 /*
8309                  * the value is:
8310                  * - counted in bytes in the request
8311                  * - counted in UNICODE chars in the max reply
8312                  * - counted in bytes in the real size
8313                  *
8314                  * take a pause *before* coding not *during* coding
8315                  */
8316
8317                 /* name */
8318                 if (r->in.value_offered) {
8319                         r->out.value_name = talloc_strdup(r, val->value_name);
8320                         if (!r->out.value_name) {
8321                                 return WERR_NOMEM;
8322                         }
8323                         *r->out.value_needed = val->value_name_len;
8324                 } else {
8325                         r->out.value_name = NULL;
8326                         *r->out.value_needed = 0;
8327                 }
8328
8329                 /* type */
8330
8331                 *r->out.type = val->type;
8332
8333                 /* data - counted in bytes */
8334
8335                 /*
8336                  * See the section "Dynamically Typed Query Parameters"
8337                  * in MS-RPRN.
8338                  */
8339
8340                 if (r->out.data && val->data && val->data->data &&
8341                                 val->data_length && r->in.data_offered) {
8342                         memcpy(r->out.data, val->data->data,
8343                                 MIN(val->data_length,r->in.data_offered));
8344                 }
8345
8346                 *r->out.data_needed = val->data_length;
8347
8348                 result = WERR_OK;
8349         }
8350
8351         return result;
8352 }
8353
8354 /****************************************************************
8355  _spoolss_SetPrinterData
8356 ****************************************************************/
8357
8358 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8359                                struct spoolss_SetPrinterData *r)
8360 {
8361         struct spoolss_SetPrinterDataEx r2;
8362
8363         r2.in.handle            = r->in.handle;
8364         r2.in.key_name          = "PrinterDriverData";
8365         r2.in.value_name        = r->in.value_name;
8366         r2.in.type              = r->in.type;
8367         r2.in.data              = r->in.data;
8368         r2.in.offered           = r->in.offered;
8369
8370         return _spoolss_SetPrinterDataEx(p, &r2);
8371 }
8372
8373 /****************************************************************
8374  _spoolss_ResetPrinter
8375 ****************************************************************/
8376
8377 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8378                              struct spoolss_ResetPrinter *r)
8379 {
8380         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8381         int             snum;
8382
8383         DEBUG(5,("_spoolss_ResetPrinter\n"));
8384
8385         /*
8386          * All we do is to check to see if the handle and queue is valid.
8387          * This call really doesn't mean anything to us because we only
8388          * support RAW printing.   --jerry
8389          */
8390
8391         if (!Printer) {
8392                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8393                         OUR_HANDLE(r->in.handle)));
8394                 return WERR_BADFID;
8395         }
8396
8397         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8398                 return WERR_BADFID;
8399
8400
8401         /* blindly return success */
8402         return WERR_OK;
8403 }
8404
8405 /****************************************************************
8406  _spoolss_DeletePrinterData
8407 ****************************************************************/
8408
8409 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8410                                   struct spoolss_DeletePrinterData *r)
8411 {
8412         struct spoolss_DeletePrinterDataEx r2;
8413
8414         r2.in.handle            = r->in.handle;
8415         r2.in.key_name          = "PrinterDriverData";
8416         r2.in.value_name        = r->in.value_name;
8417
8418         return _spoolss_DeletePrinterDataEx(p, &r2);
8419 }
8420
8421 /****************************************************************
8422  _spoolss_AddForm
8423 ****************************************************************/
8424
8425 WERROR _spoolss_AddForm(struct pipes_struct *p,
8426                         struct spoolss_AddForm *r)
8427 {
8428         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8429         int snum = -1;
8430         WERROR status = WERR_OK;
8431
8432         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8433
8434         DEBUG(5,("_spoolss_AddForm\n"));
8435
8436         if (!Printer) {
8437                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8438                         OUR_HANDLE(r->in.handle)));
8439                 return WERR_BADFID;
8440         }
8441
8442         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8443            and not a printer admin, then fail */
8444
8445         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8446             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8447             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8448                                           p->session_info->info3->base.domain.string,
8449                                           NULL,
8450                                           p->session_info->security_token,
8451                                           lp_printer_admin(snum))) {
8452                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8453                 return WERR_ACCESS_DENIED;
8454         }
8455
8456         switch (form->flags) {
8457         case SPOOLSS_FORM_USER:
8458         case SPOOLSS_FORM_BUILTIN:
8459         case SPOOLSS_FORM_PRINTER:
8460                 break;
8461         default:
8462                 return WERR_INVALID_PARAM;
8463         }
8464
8465         status = winreg_printer_addform1(p->mem_ctx,
8466                                          get_session_info_system(),
8467                                          p->msg_ctx,
8468                                          form);
8469         if (!W_ERROR_IS_OK(status)) {
8470                 return status;
8471         }
8472
8473         /*
8474          * ChangeID must always be set if this is a printer
8475          */
8476         if (Printer->printer_type == SPLHND_PRINTER) {
8477                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8478                         return WERR_BADFID;
8479                 }
8480
8481                 status = winreg_printer_update_changeid(p->mem_ctx,
8482                                                         get_session_info_system(),
8483                                                         p->msg_ctx,
8484                                                         lp_const_servicename(snum));
8485                 if (!W_ERROR_IS_OK(status)) {
8486                         return status;
8487                 }
8488         }
8489
8490         return status;
8491 }
8492
8493 /****************************************************************
8494  _spoolss_DeleteForm
8495 ****************************************************************/
8496
8497 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8498                            struct spoolss_DeleteForm *r)
8499 {
8500         const char *form_name = r->in.form_name;
8501         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8502         int snum = -1;
8503         WERROR status = WERR_OK;
8504
8505         DEBUG(5,("_spoolss_DeleteForm\n"));
8506
8507         if (!Printer) {
8508                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8509                         OUR_HANDLE(r->in.handle)));
8510                 return WERR_BADFID;
8511         }
8512
8513         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8514             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8515             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8516                                           p->session_info->info3->base.domain.string,
8517                                           NULL,
8518                                           p->session_info->security_token,
8519                                           lp_printer_admin(snum))) {
8520                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8521                 return WERR_ACCESS_DENIED;
8522         }
8523
8524         status = winreg_printer_deleteform1(p->mem_ctx,
8525                                             get_session_info_system(),
8526                                             p->msg_ctx,
8527                                             form_name);
8528         if (!W_ERROR_IS_OK(status)) {
8529                 return status;
8530         }
8531
8532         /*
8533          * ChangeID must always be set if this is a printer
8534          */
8535         if (Printer->printer_type == SPLHND_PRINTER) {
8536                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8537                         return WERR_BADFID;
8538                 }
8539
8540                 status = winreg_printer_update_changeid(p->mem_ctx,
8541                                                         get_session_info_system(),
8542                                                         p->msg_ctx,
8543                                                         lp_const_servicename(snum));
8544                 if (!W_ERROR_IS_OK(status)) {
8545                         return status;
8546                 }
8547         }
8548
8549         return status;
8550 }
8551
8552 /****************************************************************
8553  _spoolss_SetForm
8554 ****************************************************************/
8555
8556 WERROR _spoolss_SetForm(struct pipes_struct *p,
8557                         struct spoolss_SetForm *r)
8558 {
8559         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8560         const char *form_name = r->in.form_name;
8561         int snum = -1;
8562         WERROR status = WERR_OK;
8563
8564         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8565
8566         DEBUG(5,("_spoolss_SetForm\n"));
8567
8568         if (!Printer) {
8569                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8570                         OUR_HANDLE(r->in.handle)));
8571                 return WERR_BADFID;
8572         }
8573
8574         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8575            and not a printer admin, then fail */
8576
8577         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8578              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8579              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8580                                           p->session_info->info3->base.domain.string,
8581                                           NULL,
8582                                           p->session_info->security_token,
8583                                           lp_printer_admin(snum))) {
8584                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8585                 return WERR_ACCESS_DENIED;
8586         }
8587
8588         status = winreg_printer_setform1(p->mem_ctx,
8589                                          get_session_info_system(),
8590                                          p->msg_ctx,
8591                                          form_name,
8592                                          form);
8593         if (!W_ERROR_IS_OK(status)) {
8594                 return status;
8595         }
8596
8597         /*
8598          * ChangeID must always be set if this is a printer
8599          */
8600         if (Printer->printer_type == SPLHND_PRINTER) {
8601                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8602                         return WERR_BADFID;
8603                 }
8604
8605                 status = winreg_printer_update_changeid(p->mem_ctx,
8606                                                         get_session_info_system(),
8607                                                         p->msg_ctx,
8608                                                         lp_const_servicename(snum));
8609                 if (!W_ERROR_IS_OK(status)) {
8610                         return status;
8611                 }
8612         }
8613
8614         return status;
8615 }
8616
8617 /****************************************************************************
8618  fill_print_processor1
8619 ****************************************************************************/
8620
8621 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8622                                     struct spoolss_PrintProcessorInfo1 *r,
8623                                     const char *print_processor_name)
8624 {
8625         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8626         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8627
8628         return WERR_OK;
8629 }
8630
8631 /****************************************************************************
8632  enumprintprocessors level 1.
8633 ****************************************************************************/
8634
8635 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8636                                           union spoolss_PrintProcessorInfo **info_p,
8637                                           uint32_t *count)
8638 {
8639         union spoolss_PrintProcessorInfo *info;
8640         WERROR result;
8641
8642         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8643         W_ERROR_HAVE_NO_MEMORY(info);
8644
8645         *count = 1;
8646
8647         result = fill_print_processor1(info, &info[0].info1, "winprint");
8648         if (!W_ERROR_IS_OK(result)) {
8649                 goto out;
8650         }
8651
8652  out:
8653         if (!W_ERROR_IS_OK(result)) {
8654                 TALLOC_FREE(info);
8655                 *count = 0;
8656                 return result;
8657         }
8658
8659         *info_p = info;
8660
8661         return WERR_OK;
8662 }
8663
8664 /****************************************************************
8665  _spoolss_EnumPrintProcessors
8666 ****************************************************************/
8667
8668 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8669                                     struct spoolss_EnumPrintProcessors *r)
8670 {
8671         WERROR result;
8672
8673         /* that's an [in out] buffer */
8674
8675         if (!r->in.buffer && (r->in.offered != 0)) {
8676                 return WERR_INVALID_PARAM;
8677         }
8678
8679         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8680
8681         /*
8682          * Enumerate the print processors ...
8683          *
8684          * Just reply with "winprint", to keep NT happy
8685          * and I can use my nice printer checker.
8686          */
8687
8688         *r->out.count = 0;
8689         *r->out.needed = 0;
8690         *r->out.info = NULL;
8691
8692         if (!get_short_archi(r->in.environment)) {
8693                 return WERR_INVALID_ENVIRONMENT;
8694         }
8695
8696         switch (r->in.level) {
8697         case 1:
8698                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8699                                                      r->out.count);
8700                 break;
8701         default:
8702                 return WERR_UNKNOWN_LEVEL;
8703         }
8704
8705         if (!W_ERROR_IS_OK(result)) {
8706                 return result;
8707         }
8708
8709         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8710                                                      spoolss_EnumPrintProcessors,
8711                                                      *r->out.info, r->in.level,
8712                                                      *r->out.count);
8713         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8714         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8715
8716         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8717 }
8718
8719 /****************************************************************************
8720  fill_printprocdatatype1
8721 ****************************************************************************/
8722
8723 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8724                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8725                                       const char *name_array)
8726 {
8727         r->name_array = talloc_strdup(mem_ctx, name_array);
8728         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8729
8730         return WERR_OK;
8731 }
8732
8733 /****************************************************************************
8734  enumprintprocdatatypes level 1.
8735 ****************************************************************************/
8736
8737 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8738                                              union spoolss_PrintProcDataTypesInfo **info_p,
8739                                              uint32_t *count)
8740 {
8741         WERROR result;
8742         union spoolss_PrintProcDataTypesInfo *info;
8743
8744         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8745         W_ERROR_HAVE_NO_MEMORY(info);
8746
8747         *count = 1;
8748
8749         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8750         if (!W_ERROR_IS_OK(result)) {
8751                 goto out;
8752         }
8753
8754  out:
8755         if (!W_ERROR_IS_OK(result)) {
8756                 TALLOC_FREE(info);
8757                 *count = 0;
8758                 return result;
8759         }
8760
8761         *info_p = info;
8762
8763         return WERR_OK;
8764 }
8765
8766 /****************************************************************
8767  _spoolss_EnumPrintProcDataTypes
8768 ****************************************************************/
8769
8770 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8771                                        struct spoolss_EnumPrintProcDataTypes *r)
8772 {
8773         WERROR result;
8774
8775         /* that's an [in out] buffer */
8776
8777         if (!r->in.buffer && (r->in.offered != 0)) {
8778                 return WERR_INVALID_PARAM;
8779         }
8780
8781         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8782
8783         *r->out.count = 0;
8784         *r->out.needed = 0;
8785         *r->out.info = NULL;
8786
8787         if (r->in.print_processor_name == NULL ||
8788             !strequal(r->in.print_processor_name, "winprint")) {
8789                 return WERR_UNKNOWN_PRINTPROCESSOR;
8790         }
8791
8792         switch (r->in.level) {
8793         case 1:
8794                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8795                                                         r->out.count);
8796                 break;
8797         default:
8798                 return WERR_UNKNOWN_LEVEL;
8799         }
8800
8801         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8802                                                      spoolss_EnumPrintProcDataTypes,
8803                                                      *r->out.info, r->in.level,
8804                                                      *r->out.count);
8805         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8806         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8807
8808         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8809 }
8810
8811 /****************************************************************************
8812  fill_monitor_1
8813 ****************************************************************************/
8814
8815 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8816                              struct spoolss_MonitorInfo1 *r,
8817                              const char *monitor_name)
8818 {
8819         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8820         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8821
8822         return WERR_OK;
8823 }
8824
8825 /****************************************************************************
8826  fill_monitor_2
8827 ****************************************************************************/
8828
8829 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8830                              struct spoolss_MonitorInfo2 *r,
8831                              const char *monitor_name,
8832                              const char *environment,
8833                              const char *dll_name)
8834 {
8835         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8836         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8837         r->environment                  = talloc_strdup(mem_ctx, environment);
8838         W_ERROR_HAVE_NO_MEMORY(r->environment);
8839         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8840         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8841
8842         return WERR_OK;
8843 }
8844
8845 /****************************************************************************
8846  enumprintmonitors level 1.
8847 ****************************************************************************/
8848
8849 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8850                                         union spoolss_MonitorInfo **info_p,
8851                                         uint32_t *count)
8852 {
8853         union spoolss_MonitorInfo *info;
8854         WERROR result = WERR_OK;
8855
8856         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8857         W_ERROR_HAVE_NO_MEMORY(info);
8858
8859         *count = 2;
8860
8861         result = fill_monitor_1(info, &info[0].info1,
8862                                 SPL_LOCAL_PORT);
8863         if (!W_ERROR_IS_OK(result)) {
8864                 goto out;
8865         }
8866
8867         result = fill_monitor_1(info, &info[1].info1,
8868                                 SPL_TCPIP_PORT);
8869         if (!W_ERROR_IS_OK(result)) {
8870                 goto out;
8871         }
8872
8873 out:
8874         if (!W_ERROR_IS_OK(result)) {
8875                 TALLOC_FREE(info);
8876                 *count = 0;
8877                 return result;
8878         }
8879
8880         *info_p = info;
8881
8882         return WERR_OK;
8883 }
8884
8885 /****************************************************************************
8886  enumprintmonitors level 2.
8887 ****************************************************************************/
8888
8889 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8890                                         union spoolss_MonitorInfo **info_p,
8891                                         uint32_t *count)
8892 {
8893         union spoolss_MonitorInfo *info;
8894         WERROR result = WERR_OK;
8895
8896         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8897         W_ERROR_HAVE_NO_MEMORY(info);
8898
8899         *count = 2;
8900
8901         result = fill_monitor_2(info, &info[0].info2,
8902                                 SPL_LOCAL_PORT,
8903                                 "Windows NT X86", /* FIXME */
8904                                 "localmon.dll");
8905         if (!W_ERROR_IS_OK(result)) {
8906                 goto out;
8907         }
8908
8909         result = fill_monitor_2(info, &info[1].info2,
8910                                 SPL_TCPIP_PORT,
8911                                 "Windows NT X86", /* FIXME */
8912                                 "tcpmon.dll");
8913         if (!W_ERROR_IS_OK(result)) {
8914                 goto out;
8915         }
8916
8917 out:
8918         if (!W_ERROR_IS_OK(result)) {
8919                 TALLOC_FREE(info);
8920                 *count = 0;
8921                 return result;
8922         }
8923
8924         *info_p = info;
8925
8926         return WERR_OK;
8927 }
8928
8929 /****************************************************************
8930  _spoolss_EnumMonitors
8931 ****************************************************************/
8932
8933 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8934                              struct spoolss_EnumMonitors *r)
8935 {
8936         WERROR result;
8937
8938         /* that's an [in out] buffer */
8939
8940         if (!r->in.buffer && (r->in.offered != 0)) {
8941                 return WERR_INVALID_PARAM;
8942         }
8943
8944         DEBUG(5,("_spoolss_EnumMonitors\n"));
8945
8946         /*
8947          * Enumerate the print monitors ...
8948          *
8949          * Just reply with "Local Port", to keep NT happy
8950          * and I can use my nice printer checker.
8951          */
8952
8953         *r->out.count = 0;
8954         *r->out.needed = 0;
8955         *r->out.info = NULL;
8956
8957         switch (r->in.level) {
8958         case 1:
8959                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8960                                                    r->out.count);
8961                 break;
8962         case 2:
8963                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8964                                                    r->out.count);
8965                 break;
8966         default:
8967                 return WERR_UNKNOWN_LEVEL;
8968         }
8969
8970         if (!W_ERROR_IS_OK(result)) {
8971                 return result;
8972         }
8973
8974         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8975                                                      spoolss_EnumMonitors,
8976                                                      *r->out.info, r->in.level,
8977                                                      *r->out.count);
8978         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8979         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8980
8981         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8982 }
8983
8984 /****************************************************************************
8985 ****************************************************************************/
8986
8987 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8988                              const print_queue_struct *queue,
8989                              int count, int snum,
8990                              struct spoolss_PrinterInfo2 *pinfo2,
8991                              uint32_t jobid,
8992                              struct spoolss_JobInfo1 *r)
8993 {
8994         int i = 0;
8995         bool found = false;
8996
8997         for (i=0; i<count; i++) {
8998                 if (queue[i].job == (int)jobid) {
8999                         found = true;
9000                         break;
9001                 }
9002         }
9003
9004         if (found == false) {
9005                 /* NT treats not found as bad param... yet another bad choice */
9006                 return WERR_INVALID_PARAM;
9007         }
9008
9009         return fill_job_info1(mem_ctx,
9010                               r,
9011                               &queue[i],
9012                               i,
9013                               snum,
9014                               pinfo2);
9015 }
9016
9017 /****************************************************************************
9018 ****************************************************************************/
9019
9020 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9021                              const print_queue_struct *queue,
9022                              int count, int snum,
9023                              struct spoolss_PrinterInfo2 *pinfo2,
9024                              uint32_t jobid,
9025                              struct spoolss_JobInfo2 *r)
9026 {
9027         int i = 0;
9028         bool found = false;
9029         struct spoolss_DeviceMode *devmode;
9030         WERROR result;
9031
9032         for (i=0; i<count; i++) {
9033                 if (queue[i].job == (int)jobid) {
9034                         found = true;
9035                         break;
9036                 }
9037         }
9038
9039         if (found == false) {
9040                 /* NT treats not found as bad param... yet another bad
9041                    choice */
9042                 return WERR_INVALID_PARAM;
9043         }
9044
9045         /*
9046          * if the print job does not have a DEVMODE associated with it,
9047          * just use the one for the printer. A NULL devicemode is not
9048          *  a failure condition
9049          */
9050
9051         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9052         if (!devmode) {
9053                 result = spoolss_create_default_devmode(mem_ctx,
9054                                                 pinfo2->printername,
9055                                                 &devmode);
9056                 if (!W_ERROR_IS_OK(result)) {
9057                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9058                         return result;
9059                 }
9060         }
9061
9062         return fill_job_info2(mem_ctx,
9063                               r,
9064                               &queue[i],
9065                               i,
9066                               snum,
9067                               pinfo2,
9068                               devmode);
9069 }
9070
9071 /****************************************************************
9072  _spoolss_GetJob
9073 ****************************************************************/
9074
9075 WERROR _spoolss_GetJob(struct pipes_struct *p,
9076                        struct spoolss_GetJob *r)
9077 {
9078         WERROR result = WERR_OK;
9079         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9080         int snum;
9081         int count;
9082         print_queue_struct      *queue = NULL;
9083         print_status_struct prt_status;
9084
9085         /* that's an [in out] buffer */
9086
9087         if (!r->in.buffer && (r->in.offered != 0)) {
9088                 return WERR_INVALID_PARAM;
9089         }
9090
9091         DEBUG(5,("_spoolss_GetJob\n"));
9092
9093         *r->out.needed = 0;
9094
9095         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9096                 return WERR_BADFID;
9097         }
9098
9099         result = winreg_get_printer(p->mem_ctx,
9100                                     get_session_info_system(),
9101                                     p->msg_ctx,
9102                                     lp_const_servicename(snum),
9103                                     &pinfo2);
9104         if (!W_ERROR_IS_OK(result)) {
9105                 return result;
9106         }
9107
9108         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9109
9110         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9111                      count, prt_status.status, prt_status.message));
9112
9113         switch (r->in.level) {
9114         case 1:
9115                 result = getjob_level_1(p->mem_ctx,
9116                                         queue, count, snum, pinfo2,
9117                                         r->in.job_id, &r->out.info->info1);
9118                 break;
9119         case 2:
9120                 result = getjob_level_2(p->mem_ctx,
9121                                         queue, count, snum, pinfo2,
9122                                         r->in.job_id, &r->out.info->info2);
9123                 break;
9124         default:
9125                 result = WERR_UNKNOWN_LEVEL;
9126                 break;
9127         }
9128
9129         SAFE_FREE(queue);
9130         TALLOC_FREE(pinfo2);
9131
9132         if (!W_ERROR_IS_OK(result)) {
9133                 TALLOC_FREE(r->out.info);
9134                 return result;
9135         }
9136
9137         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9138                                                                                    r->in.level);
9139         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9140
9141         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9142 }
9143
9144 /****************************************************************
9145  _spoolss_GetPrinterDataEx
9146 ****************************************************************/
9147
9148 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9149                                  struct spoolss_GetPrinterDataEx *r)
9150 {
9151
9152         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9153         const char *printer;
9154         int                     snum = 0;
9155         WERROR result = WERR_OK;
9156         DATA_BLOB blob;
9157         enum winreg_Type val_type;
9158         uint8_t *val_data;
9159         uint32_t val_size;
9160
9161
9162         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9163
9164         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9165                 r->in.key_name, r->in.value_name));
9166
9167         /* in case of problem, return some default values */
9168
9169         *r->out.needed  = 0;
9170         *r->out.type    = REG_NONE;
9171
9172         if (!Printer) {
9173                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9174                         OUR_HANDLE(r->in.handle)));
9175                 result = WERR_BADFID;
9176                 goto done;
9177         }
9178
9179         /* Is the handle to a printer or to the server? */
9180
9181         if (Printer->printer_type == SPLHND_SERVER) {
9182
9183                 union spoolss_PrinterData data;
9184
9185                 result = getprinterdata_printer_server(p->mem_ctx,
9186                                                        r->in.value_name,
9187                                                        r->out.type,
9188                                                        &data);
9189                 if (!W_ERROR_IS_OK(result)) {
9190                         return result;
9191                 }
9192
9193                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9194                                                   *r->out.type, &data);
9195                 if (!W_ERROR_IS_OK(result)) {
9196                         return result;
9197                 }
9198
9199                 *r->out.needed = blob.length;
9200
9201                 if (r->in.offered >= *r->out.needed) {
9202                         memcpy(r->out.data, blob.data, blob.length);
9203                 }
9204
9205                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9206         }
9207
9208         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9209                 return WERR_BADFID;
9210         }
9211         printer = lp_const_servicename(snum);
9212
9213         /* check to see if the keyname is valid */
9214         if (!strlen(r->in.key_name)) {
9215                 return WERR_INVALID_PARAM;
9216         }
9217
9218         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9219         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9220             strequal(r->in.value_name, "ChangeId")) {
9221                 *r->out.type = REG_DWORD;
9222                 *r->out.needed = 4;
9223                 if (r->in.offered >= *r->out.needed) {
9224                         uint32_t changeid = 0;
9225
9226                         result = winreg_printer_get_changeid(p->mem_ctx,
9227                                                              get_session_info_system(),
9228                                                              p->msg_ctx,
9229                                                              printer,
9230                                                              &changeid);
9231                         if (!W_ERROR_IS_OK(result)) {
9232                                 return result;
9233                         }
9234
9235                         SIVAL(r->out.data, 0, changeid);
9236                         result = WERR_OK;
9237                 }
9238                 goto done;
9239         }
9240
9241         result = winreg_get_printer_dataex(p->mem_ctx,
9242                                            get_session_info_system(),
9243                                            p->msg_ctx,
9244                                            printer,
9245                                            r->in.key_name,
9246                                            r->in.value_name,
9247                                            &val_type,
9248                                            &val_data,
9249                                            &val_size);
9250         if (!W_ERROR_IS_OK(result)) {
9251                 return result;
9252         }
9253
9254         *r->out.needed = val_size;
9255         *r->out.type = val_type;
9256
9257         if (r->in.offered >= *r->out.needed) {
9258                 memcpy(r->out.data, val_data, val_size);
9259         }
9260
9261  done:
9262         /* retain type when returning WERR_MORE_DATA */
9263         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9264
9265         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9266 }
9267
9268 /****************************************************************
9269  _spoolss_SetPrinterDataEx
9270 ****************************************************************/
9271
9272 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9273                                  struct spoolss_SetPrinterDataEx *r)
9274 {
9275         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9276         int                     snum = 0;
9277         WERROR                  result = WERR_OK;
9278         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9279         char                    *oid_string;
9280
9281         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9282
9283         /* From MSDN documentation of SetPrinterDataEx: pass request to
9284            SetPrinterData if key is "PrinterDriverData" */
9285
9286         if (!Printer) {
9287                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9288                         OUR_HANDLE(r->in.handle)));
9289                 return WERR_BADFID;
9290         }
9291
9292         if (Printer->printer_type == SPLHND_SERVER) {
9293                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9294                         "Not implemented for server handles yet\n"));
9295                 return WERR_INVALID_PARAM;
9296         }
9297
9298         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9299                 return WERR_BADFID;
9300         }
9301
9302         /*
9303          * Access check : NT returns "access denied" if you make a
9304          * SetPrinterData call without the necessary privildge.
9305          * we were originally returning OK if nothing changed
9306          * which made Win2k issue **a lot** of SetPrinterData
9307          * when connecting to a printer  --jerry
9308          */
9309
9310         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9311                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9312                         "change denied by handle access permissions\n"));
9313                 return WERR_ACCESS_DENIED;
9314         }
9315
9316         result = winreg_get_printer(Printer,
9317                                     get_session_info_system(),
9318                                     p->msg_ctx,
9319                                     lp_servicename(snum),
9320                                     &pinfo2);
9321         if (!W_ERROR_IS_OK(result)) {
9322                 return result;
9323         }
9324
9325         /* check for OID in valuename */
9326
9327         oid_string = strchr(r->in.value_name, ',');
9328         if (oid_string) {
9329                 *oid_string = '\0';
9330                 oid_string++;
9331         }
9332
9333         /* save the registry data */
9334
9335         result = winreg_set_printer_dataex(p->mem_ctx,
9336                                            get_session_info_system(),
9337                                            p->msg_ctx,
9338                                            pinfo2->sharename,
9339                                            r->in.key_name,
9340                                            r->in.value_name,
9341                                            r->in.type,
9342                                            r->in.data,
9343                                            r->in.offered);
9344
9345         if (W_ERROR_IS_OK(result)) {
9346                 /* save the OID if one was specified */
9347                 if (oid_string) {
9348                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9349                                 r->in.key_name, SPOOL_OID_KEY);
9350                         if (!str) {
9351                                 result = WERR_NOMEM;
9352                                 goto done;
9353                         }
9354
9355                         /*
9356                          * I'm not checking the status here on purpose.  Don't know
9357                          * if this is right, but I'm returning the status from the
9358                          * previous set_printer_dataex() call.  I have no idea if
9359                          * this is right.    --jerry
9360                          */
9361                         winreg_set_printer_dataex(p->mem_ctx,
9362                                                   get_session_info_system(),
9363                                                   p->msg_ctx,
9364                                                   pinfo2->sharename,
9365                                                   str,
9366                                                   r->in.value_name,
9367                                                   REG_SZ,
9368                                                   (uint8_t *) oid_string,
9369                                                   strlen(oid_string) + 1);
9370                 }
9371
9372                 result = winreg_printer_update_changeid(p->mem_ctx,
9373                                                         get_session_info_system(),
9374                                                         p->msg_ctx,
9375                                                         lp_const_servicename(snum));
9376
9377         }
9378
9379 done:
9380         talloc_free(pinfo2);
9381         return result;
9382 }
9383
9384 /****************************************************************
9385  _spoolss_DeletePrinterDataEx
9386 ****************************************************************/
9387
9388 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9389                                     struct spoolss_DeletePrinterDataEx *r)
9390 {
9391         const char *printer;
9392         int             snum=0;
9393         WERROR          status = WERR_OK;
9394         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9395
9396         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9397
9398         if (!Printer) {
9399                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9400                         "Invalid handle (%s:%u:%u).\n",
9401                         OUR_HANDLE(r->in.handle)));
9402                 return WERR_BADFID;
9403         }
9404
9405         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9406                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9407                         "printer properties change denied by handle\n"));
9408                 return WERR_ACCESS_DENIED;
9409         }
9410
9411         if (!r->in.value_name || !r->in.key_name) {
9412                 return WERR_NOMEM;
9413         }
9414
9415         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9416                 return WERR_BADFID;
9417         }
9418         printer = lp_const_servicename(snum);
9419
9420         status = winreg_delete_printer_dataex(p->mem_ctx,
9421                                               get_session_info_system(),
9422                                               p->msg_ctx,
9423                                               printer,
9424                                               r->in.key_name,
9425                                               r->in.value_name);
9426         if (W_ERROR_IS_OK(status)) {
9427                 status = winreg_printer_update_changeid(p->mem_ctx,
9428                                                         get_session_info_system(),
9429                                                         p->msg_ctx,
9430                                                         printer);
9431         }
9432
9433         return status;
9434 }
9435
9436 /****************************************************************
9437  _spoolss_EnumPrinterKey
9438 ****************************************************************/
9439
9440 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9441                                struct spoolss_EnumPrinterKey *r)
9442 {
9443         uint32_t        num_keys;
9444         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9445         int             snum = 0;
9446         WERROR          result = WERR_BADFILE;
9447         const char **array = NULL;
9448         DATA_BLOB blob;
9449
9450         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9451
9452         if (!Printer) {
9453                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9454                         OUR_HANDLE(r->in.handle)));
9455                 return WERR_BADFID;
9456         }
9457
9458         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9459                 return WERR_BADFID;
9460         }
9461
9462         result = winreg_enum_printer_key(p->mem_ctx,
9463                                          get_session_info_system(),
9464                                          p->msg_ctx,
9465                                          lp_const_servicename(snum),
9466                                          r->in.key_name,
9467                                          &num_keys,
9468                                          &array);
9469         if (!W_ERROR_IS_OK(result)) {
9470                 goto done;
9471         }
9472
9473         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9474                 result = WERR_NOMEM;
9475                 goto done;
9476         }
9477
9478         *r->out._ndr_size = r->in.offered / 2;
9479         *r->out.needed = blob.length;
9480
9481         if (r->in.offered < *r->out.needed) {
9482                 result = WERR_MORE_DATA;
9483         } else {
9484                 result = WERR_OK;
9485                 r->out.key_buffer->string_array = array;
9486         }
9487
9488  done:
9489         if (!W_ERROR_IS_OK(result)) {
9490                 TALLOC_FREE(array);
9491                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9492                         *r->out.needed = 0;
9493                 }
9494         }
9495
9496         return result;
9497 }
9498
9499 /****************************************************************
9500  _spoolss_DeletePrinterKey
9501 ****************************************************************/
9502
9503 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9504                                  struct spoolss_DeletePrinterKey *r)
9505 {
9506         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9507         int                     snum=0;
9508         WERROR                  status;
9509         const char *printer;
9510
9511         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9512
9513         if (!Printer) {
9514                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9515                         OUR_HANDLE(r->in.handle)));
9516                 return WERR_BADFID;
9517         }
9518
9519         /* if keyname == NULL, return error */
9520         if ( !r->in.key_name )
9521                 return WERR_INVALID_PARAM;
9522
9523         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9524                 return WERR_BADFID;
9525         }
9526
9527         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9528                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9529                         "printer properties change denied by handle\n"));
9530                 return WERR_ACCESS_DENIED;
9531         }
9532
9533         printer = lp_const_servicename(snum);
9534
9535         /* delete the key and all subkeys */
9536         status = winreg_delete_printer_key(p->mem_ctx,
9537                                            get_session_info_system(),
9538                                            p->msg_ctx,
9539                                            printer,
9540                                            r->in.key_name);
9541         if (W_ERROR_IS_OK(status)) {
9542                 status = winreg_printer_update_changeid(p->mem_ctx,
9543                                                         get_session_info_system(),
9544                                                         p->msg_ctx,
9545                                                         printer);
9546         }
9547
9548         return status;
9549 }
9550
9551 /****************************************************************
9552  _spoolss_EnumPrinterDataEx
9553 ****************************************************************/
9554
9555 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9556                                   struct spoolss_EnumPrinterDataEx *r)
9557 {
9558         uint32_t        count = 0;
9559         struct spoolss_PrinterEnumValues *info = NULL;
9560         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9561         int             snum;
9562         WERROR          result;
9563
9564         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9565
9566         *r->out.count = 0;
9567         *r->out.needed = 0;
9568         *r->out.info = NULL;
9569
9570         if (!Printer) {
9571                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9572                         OUR_HANDLE(r->in.handle)));
9573                 return WERR_BADFID;
9574         }
9575
9576         /*
9577          * first check for a keyname of NULL or "".  Win2k seems to send
9578          * this a lot and we should send back WERR_INVALID_PARAM
9579          * no need to spend time looking up the printer in this case.
9580          * --jerry
9581          */
9582
9583         if (!strlen(r->in.key_name)) {
9584                 result = WERR_INVALID_PARAM;
9585                 goto done;
9586         }
9587
9588         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9589                 return WERR_BADFID;
9590         }
9591
9592         /* now look for a match on the key name */
9593         result = winreg_enum_printer_dataex(p->mem_ctx,
9594                                             get_session_info_system(),
9595                                             p->msg_ctx,
9596                                             lp_const_servicename(snum),
9597                                             r->in.key_name,
9598                                             &count,
9599                                             &info);
9600         if (!W_ERROR_IS_OK(result)) {
9601                 goto done;
9602         }
9603
9604 #if 0 /* FIXME - gd */
9605         /* housekeeping information in the reply */
9606
9607         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9608          * the hand marshalled container size is a multiple
9609          * of 4 bytes for RPC alignment.
9610          */
9611
9612         if (needed % 4) {
9613                 needed += 4-(needed % 4);
9614         }
9615 #endif
9616         *r->out.count   = count;
9617         *r->out.info    = info;
9618
9619  done:
9620         if (!W_ERROR_IS_OK(result)) {
9621                 return result;
9622         }
9623
9624         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9625                                                spoolss_EnumPrinterDataEx,
9626                                                *r->out.info,
9627                                                *r->out.count);
9628         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9629         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9630
9631         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9632 }
9633
9634 /****************************************************************************
9635 ****************************************************************************/
9636
9637 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9638                                                  const char *servername,
9639                                                  const char *environment,
9640                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9641 {
9642         WERROR werr;
9643         char *path = NULL;
9644
9645         werr = compose_spoolss_server_path(mem_ctx,
9646                                            servername,
9647                                            environment,
9648                                            SPOOLSS_PRTPROCS_PATH,
9649                                            &path);
9650         if (!W_ERROR_IS_OK(werr)) {
9651                 return werr;
9652         }
9653
9654         DEBUG(4,("print processor directory: [%s]\n", path));
9655
9656         r->directory_name = path;
9657
9658         return WERR_OK;
9659 }
9660
9661 /****************************************************************
9662  _spoolss_GetPrintProcessorDirectory
9663 ****************************************************************/
9664
9665 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9666                                            struct spoolss_GetPrintProcessorDirectory *r)
9667 {
9668         WERROR result;
9669         char *prnproc_share = NULL;
9670         bool prnproc_share_exists = false;
9671         int snum;
9672
9673         /* that's an [in out] buffer */
9674
9675         if (!r->in.buffer && (r->in.offered != 0)) {
9676                 return WERR_INVALID_PARAM;
9677         }
9678
9679         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9680                 r->in.level));
9681
9682         *r->out.needed = 0;
9683
9684         /* r->in.level is ignored */
9685
9686         /* We always should reply with a local print processor directory so that
9687          * users are not forced to have a [prnproc$] share on the Samba spoolss
9688          * server, if users decide to do so, lets announce it though - Guenther */
9689
9690         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9691         if (!prnproc_share) {
9692                 return WERR_NOMEM;
9693         }
9694         if (snum != -1) {
9695                 prnproc_share_exists = true;
9696         }
9697
9698         result = getprintprocessordirectory_level_1(p->mem_ctx,
9699                                                     prnproc_share_exists ? r->in.server : NULL,
9700                                                     r->in.environment,
9701                                                     &r->out.info->info1);
9702         if (!W_ERROR_IS_OK(result)) {
9703                 TALLOC_FREE(r->out.info);
9704                 return result;
9705         }
9706
9707         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9708                                                                                    r->out.info, r->in.level);
9709         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9710
9711         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9712 }
9713
9714 /*******************************************************************
9715  ********************************************************************/
9716
9717 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9718                                const char *dllname)
9719 {
9720         enum ndr_err_code ndr_err;
9721         struct spoolss_MonitorUi ui;
9722
9723         ui.dll_name = dllname;
9724
9725         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9726                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9727         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9728                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9729         }
9730         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9731 }
9732
9733 /*******************************************************************
9734  Streams the monitor UI DLL name in UNICODE
9735 *******************************************************************/
9736
9737 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9738                                struct security_token *token, DATA_BLOB *in,
9739                                DATA_BLOB *out, uint32_t *needed)
9740 {
9741         const char *dllname = "tcpmonui.dll";
9742
9743         *needed = (strlen(dllname)+1) * 2;
9744
9745         if (out->length < *needed) {
9746                 return WERR_INSUFFICIENT_BUFFER;
9747         }
9748
9749         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9750                 return WERR_NOMEM;
9751         }
9752
9753         return WERR_OK;
9754 }
9755
9756 /*******************************************************************
9757  ********************************************************************/
9758
9759 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9760                              struct spoolss_PortData1 *port1,
9761                              const DATA_BLOB *buf)
9762 {
9763         enum ndr_err_code ndr_err;
9764         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9765                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9766         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9767                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9768         }
9769         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9770 }
9771
9772 /*******************************************************************
9773  ********************************************************************/
9774
9775 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9776                              struct spoolss_PortData2 *port2,
9777                              const DATA_BLOB *buf)
9778 {
9779         enum ndr_err_code ndr_err;
9780         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9781                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9782         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9783                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9784         }
9785         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9786 }
9787
9788 /*******************************************************************
9789  Create a new TCP/IP port
9790 *******************************************************************/
9791
9792 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9793                              struct security_token *token, DATA_BLOB *in,
9794                              DATA_BLOB *out, uint32_t *needed)
9795 {
9796         struct spoolss_PortData1 port1;
9797         struct spoolss_PortData2 port2;
9798         char *device_uri = NULL;
9799         uint32_t version;
9800
9801         const char *portname;
9802         const char *hostaddress;
9803         const char *queue;
9804         uint32_t port_number;
9805         uint32_t protocol;
9806
9807         /* peek for spoolss_PortData version */
9808
9809         if (!in || (in->length < (128 + 4))) {
9810                 return WERR_GENERAL_FAILURE;
9811         }
9812
9813         version = IVAL(in->data, 128);
9814
9815         switch (version) {
9816                 case 1:
9817                         ZERO_STRUCT(port1);
9818
9819                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9820                                 return WERR_NOMEM;
9821                         }
9822
9823                         portname        = port1.portname;
9824                         hostaddress     = port1.hostaddress;
9825                         queue           = port1.queue;
9826                         protocol        = port1.protocol;
9827                         port_number     = port1.port_number;
9828
9829                         break;
9830                 case 2:
9831                         ZERO_STRUCT(port2);
9832
9833                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9834                                 return WERR_NOMEM;
9835                         }
9836
9837                         portname        = port2.portname;
9838                         hostaddress     = port2.hostaddress;
9839                         queue           = port2.queue;
9840                         protocol        = port2.protocol;
9841                         port_number     = port2.port_number;
9842
9843                         break;
9844                 default:
9845                         DEBUG(1,("xcvtcp_addport: "
9846                                 "unknown version of port_data: %d\n", version));
9847                         return WERR_UNKNOWN_PORT;
9848         }
9849
9850         /* create the device URI and call the add_port_hook() */
9851
9852         switch (protocol) {
9853         case PROTOCOL_RAWTCP_TYPE:
9854                 device_uri = talloc_asprintf(mem_ctx,
9855                                 "socket://%s:%d/", hostaddress,
9856                                 port_number);
9857                 break;
9858
9859         case PROTOCOL_LPR_TYPE:
9860                 device_uri = talloc_asprintf(mem_ctx,
9861                         "lpr://%s/%s", hostaddress, queue );
9862                 break;
9863
9864         default:
9865                 return WERR_UNKNOWN_PORT;
9866         }
9867
9868         if (!device_uri) {
9869                 return WERR_NOMEM;
9870         }
9871
9872         return add_port_hook(mem_ctx, token, portname, device_uri);
9873 }
9874
9875 /*******************************************************************
9876 *******************************************************************/
9877
9878 struct xcv_api_table xcvtcp_cmds[] = {
9879         { "MonitorUI",  xcvtcp_monitorui },
9880         { "AddPort",    xcvtcp_addport},
9881         { NULL,         NULL }
9882 };
9883
9884 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9885                                      struct security_token *token, const char *command,
9886                                      DATA_BLOB *inbuf,
9887                                      DATA_BLOB *outbuf,
9888                                      uint32_t *needed )
9889 {
9890         int i;
9891
9892         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9893
9894         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9895                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9896                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9897         }
9898
9899         return WERR_BADFUNC;
9900 }
9901
9902 /*******************************************************************
9903 *******************************************************************/
9904 #if 0   /* don't support management using the "Local Port" monitor */
9905
9906 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9907                                  struct security_token *token, DATA_BLOB *in,
9908                                  DATA_BLOB *out, uint32_t *needed)
9909 {
9910         const char *dllname = "localui.dll";
9911
9912         *needed = (strlen(dllname)+1) * 2;
9913
9914         if (out->length < *needed) {
9915                 return WERR_INSUFFICIENT_BUFFER;
9916         }
9917
9918         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9919                 return WERR_NOMEM;
9920         }
9921
9922         return WERR_OK;
9923 }
9924
9925 /*******************************************************************
9926 *******************************************************************/
9927
9928 struct xcv_api_table xcvlocal_cmds[] = {
9929         { "MonitorUI",  xcvlocal_monitorui },
9930         { NULL,         NULL }
9931 };
9932 #else
9933 struct xcv_api_table xcvlocal_cmds[] = {
9934         { NULL,         NULL }
9935 };
9936 #endif
9937
9938
9939
9940 /*******************************************************************
9941 *******************************************************************/
9942
9943 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9944                                        struct security_token *token, const char *command,
9945                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9946                                        uint32_t *needed)
9947 {
9948         int i;
9949
9950         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9951
9952         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9953                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9954                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9955         }
9956         return WERR_BADFUNC;
9957 }
9958
9959 /****************************************************************
9960  _spoolss_XcvData
9961 ****************************************************************/
9962
9963 WERROR _spoolss_XcvData(struct pipes_struct *p,
9964                         struct spoolss_XcvData *r)
9965 {
9966         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9967         DATA_BLOB out_data = data_blob_null;
9968         WERROR werror;
9969
9970         if (!Printer) {
9971                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9972                         OUR_HANDLE(r->in.handle)));
9973                 return WERR_BADFID;
9974         }
9975
9976         /* Has to be a handle to the TCP/IP port monitor */
9977
9978         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9979                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9980                 return WERR_BADFID;
9981         }
9982
9983         /* requires administrative access to the server */
9984
9985         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9986                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9987                 return WERR_ACCESS_DENIED;
9988         }
9989
9990         /* Allocate the outgoing buffer */
9991
9992         if (r->in.out_data_size) {
9993                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9994                 if (out_data.data == NULL) {
9995                         return WERR_NOMEM;
9996                 }
9997         }
9998
9999         switch ( Printer->printer_type ) {
10000         case SPLHND_PORTMON_TCP:
10001                 werror = process_xcvtcp_command(p->mem_ctx,
10002                                                 p->session_info->security_token,
10003                                                 r->in.function_name,
10004                                                 &r->in.in_data, &out_data,
10005                                                 r->out.needed);
10006                 break;
10007         case SPLHND_PORTMON_LOCAL:
10008                 werror = process_xcvlocal_command(p->mem_ctx,
10009                                                   p->session_info->security_token,
10010                                                   r->in.function_name,
10011                                                   &r->in.in_data, &out_data,
10012                                                   r->out.needed);
10013                 break;
10014         default:
10015                 werror = WERR_INVALID_PRINT_MONITOR;
10016         }
10017
10018         if (!W_ERROR_IS_OK(werror)) {
10019                 return werror;
10020         }
10021
10022         *r->out.status_code = 0;
10023
10024         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10025                 memcpy(r->out.out_data, out_data.data,
10026                         MIN(r->in.out_data_size, out_data.length));
10027         }
10028
10029         return WERR_OK;
10030 }
10031
10032 /****************************************************************
10033  _spoolss_AddPrintProcessor
10034 ****************************************************************/
10035
10036 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10037                                   struct spoolss_AddPrintProcessor *r)
10038 {
10039         /* for now, just indicate success and ignore the add.  We'll
10040            automatically set the winprint processor for printer
10041            entries later.  Used to debug the LexMark Optra S 1855 PCL
10042            driver --jerry */
10043
10044         return WERR_OK;
10045 }
10046
10047 /****************************************************************
10048  _spoolss_AddPort
10049 ****************************************************************/
10050
10051 WERROR _spoolss_AddPort(struct pipes_struct *p,
10052                         struct spoolss_AddPort *r)
10053 {
10054         /* do what w2k3 does */
10055
10056         return WERR_NOT_SUPPORTED;
10057 }
10058
10059 /****************************************************************
10060  _spoolss_GetPrinterDriver
10061 ****************************************************************/
10062
10063 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10064                                  struct spoolss_GetPrinterDriver *r)
10065 {
10066         p->rng_fault_state = true;
10067         return WERR_NOT_SUPPORTED;
10068 }
10069
10070 /****************************************************************
10071  _spoolss_ReadPrinter
10072 ****************************************************************/
10073
10074 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10075                             struct spoolss_ReadPrinter *r)
10076 {
10077         p->rng_fault_state = true;
10078         return WERR_NOT_SUPPORTED;
10079 }
10080
10081 /****************************************************************
10082  _spoolss_WaitForPrinterChange
10083 ****************************************************************/
10084
10085 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10086                                      struct spoolss_WaitForPrinterChange *r)
10087 {
10088         p->rng_fault_state = true;
10089         return WERR_NOT_SUPPORTED;
10090 }
10091
10092 /****************************************************************
10093  _spoolss_ConfigurePort
10094 ****************************************************************/
10095
10096 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10097                               struct spoolss_ConfigurePort *r)
10098 {
10099         p->rng_fault_state = true;
10100         return WERR_NOT_SUPPORTED;
10101 }
10102
10103 /****************************************************************
10104  _spoolss_DeletePort
10105 ****************************************************************/
10106
10107 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10108                            struct spoolss_DeletePort *r)
10109 {
10110         p->rng_fault_state = true;
10111         return WERR_NOT_SUPPORTED;
10112 }
10113
10114 /****************************************************************
10115  _spoolss_CreatePrinterIC
10116 ****************************************************************/
10117
10118 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10119                                 struct spoolss_CreatePrinterIC *r)
10120 {
10121         p->rng_fault_state = true;
10122         return WERR_NOT_SUPPORTED;
10123 }
10124
10125 /****************************************************************
10126  _spoolss_PlayGDIScriptOnPrinterIC
10127 ****************************************************************/
10128
10129 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10130                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10131 {
10132         p->rng_fault_state = true;
10133         return WERR_NOT_SUPPORTED;
10134 }
10135
10136 /****************************************************************
10137  _spoolss_DeletePrinterIC
10138 ****************************************************************/
10139
10140 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10141                                 struct spoolss_DeletePrinterIC *r)
10142 {
10143         p->rng_fault_state = true;
10144         return WERR_NOT_SUPPORTED;
10145 }
10146
10147 /****************************************************************
10148  _spoolss_AddPrinterConnection
10149 ****************************************************************/
10150
10151 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10152                                      struct spoolss_AddPrinterConnection *r)
10153 {
10154         p->rng_fault_state = true;
10155         return WERR_NOT_SUPPORTED;
10156 }
10157
10158 /****************************************************************
10159  _spoolss_DeletePrinterConnection
10160 ****************************************************************/
10161
10162 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10163                                         struct spoolss_DeletePrinterConnection *r)
10164 {
10165         p->rng_fault_state = true;
10166         return WERR_NOT_SUPPORTED;
10167 }
10168
10169 /****************************************************************
10170  _spoolss_PrinterMessageBox
10171 ****************************************************************/
10172
10173 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10174                                   struct spoolss_PrinterMessageBox *r)
10175 {
10176         p->rng_fault_state = true;
10177         return WERR_NOT_SUPPORTED;
10178 }
10179
10180 /****************************************************************
10181  _spoolss_AddMonitor
10182 ****************************************************************/
10183
10184 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10185                            struct spoolss_AddMonitor *r)
10186 {
10187         p->rng_fault_state = true;
10188         return WERR_NOT_SUPPORTED;
10189 }
10190
10191 /****************************************************************
10192  _spoolss_DeleteMonitor
10193 ****************************************************************/
10194
10195 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10196                               struct spoolss_DeleteMonitor *r)
10197 {
10198         p->rng_fault_state = true;
10199         return WERR_NOT_SUPPORTED;
10200 }
10201
10202 /****************************************************************
10203  _spoolss_DeletePrintProcessor
10204 ****************************************************************/
10205
10206 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10207                                      struct spoolss_DeletePrintProcessor *r)
10208 {
10209         p->rng_fault_state = true;
10210         return WERR_NOT_SUPPORTED;
10211 }
10212
10213 /****************************************************************
10214  _spoolss_AddPrintProvidor
10215 ****************************************************************/
10216
10217 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10218                                  struct spoolss_AddPrintProvidor *r)
10219 {
10220         p->rng_fault_state = true;
10221         return WERR_NOT_SUPPORTED;
10222 }
10223
10224 /****************************************************************
10225  _spoolss_DeletePrintProvidor
10226 ****************************************************************/
10227
10228 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10229                                     struct spoolss_DeletePrintProvidor *r)
10230 {
10231         p->rng_fault_state = true;
10232         return WERR_NOT_SUPPORTED;
10233 }
10234
10235 /****************************************************************
10236  _spoolss_FindFirstPrinterChangeNotification
10237 ****************************************************************/
10238
10239 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10240                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10241 {
10242         p->rng_fault_state = true;
10243         return WERR_NOT_SUPPORTED;
10244 }
10245
10246 /****************************************************************
10247  _spoolss_FindNextPrinterChangeNotification
10248 ****************************************************************/
10249
10250 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10251                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10252 {
10253         p->rng_fault_state = true;
10254         return WERR_NOT_SUPPORTED;
10255 }
10256
10257 /****************************************************************
10258  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10259 ****************************************************************/
10260
10261 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10262                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10263 {
10264         p->rng_fault_state = true;
10265         return WERR_NOT_SUPPORTED;
10266 }
10267
10268 /****************************************************************
10269  _spoolss_ReplyOpenPrinter
10270 ****************************************************************/
10271
10272 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10273                                  struct spoolss_ReplyOpenPrinter *r)
10274 {
10275         p->rng_fault_state = true;
10276         return WERR_NOT_SUPPORTED;
10277 }
10278
10279 /****************************************************************
10280  _spoolss_RouterReplyPrinter
10281 ****************************************************************/
10282
10283 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10284                                    struct spoolss_RouterReplyPrinter *r)
10285 {
10286         p->rng_fault_state = true;
10287         return WERR_NOT_SUPPORTED;
10288 }
10289
10290 /****************************************************************
10291  _spoolss_ReplyClosePrinter
10292 ****************************************************************/
10293
10294 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10295                                   struct spoolss_ReplyClosePrinter *r)
10296 {
10297         p->rng_fault_state = true;
10298         return WERR_NOT_SUPPORTED;
10299 }
10300
10301 /****************************************************************
10302  _spoolss_AddPortEx
10303 ****************************************************************/
10304
10305 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10306                           struct spoolss_AddPortEx *r)
10307 {
10308         p->rng_fault_state = true;
10309         return WERR_NOT_SUPPORTED;
10310 }
10311
10312 /****************************************************************
10313  _spoolss_RouterFindFirstPrinterChangeNotification
10314 ****************************************************************/
10315
10316 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10317                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10318 {
10319         p->rng_fault_state = true;
10320         return WERR_NOT_SUPPORTED;
10321 }
10322
10323 /****************************************************************
10324  _spoolss_SpoolerInit
10325 ****************************************************************/
10326
10327 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10328                             struct spoolss_SpoolerInit *r)
10329 {
10330         p->rng_fault_state = true;
10331         return WERR_NOT_SUPPORTED;
10332 }
10333
10334 /****************************************************************
10335  _spoolss_ResetPrinterEx
10336 ****************************************************************/
10337
10338 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10339                                struct spoolss_ResetPrinterEx *r)
10340 {
10341         p->rng_fault_state = true;
10342         return WERR_NOT_SUPPORTED;
10343 }
10344
10345 /****************************************************************
10346  _spoolss_RouterReplyPrinterEx
10347 ****************************************************************/
10348
10349 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10350                                      struct spoolss_RouterReplyPrinterEx *r)
10351 {
10352         p->rng_fault_state = true;
10353         return WERR_NOT_SUPPORTED;
10354 }
10355
10356 /****************************************************************
10357  _spoolss_44
10358 ****************************************************************/
10359
10360 WERROR _spoolss_44(struct pipes_struct *p,
10361                    struct spoolss_44 *r)
10362 {
10363         p->rng_fault_state = true;
10364         return WERR_NOT_SUPPORTED;
10365 }
10366
10367 /****************************************************************
10368  _spoolss_SetPort
10369 ****************************************************************/
10370
10371 WERROR _spoolss_SetPort(struct pipes_struct *p,
10372                         struct spoolss_SetPort *r)
10373 {
10374         p->rng_fault_state = true;
10375         return WERR_NOT_SUPPORTED;
10376 }
10377
10378 /****************************************************************
10379  _spoolss_4a
10380 ****************************************************************/
10381
10382 WERROR _spoolss_4a(struct pipes_struct *p,
10383                    struct spoolss_4a *r)
10384 {
10385         p->rng_fault_state = true;
10386         return WERR_NOT_SUPPORTED;
10387 }
10388
10389 /****************************************************************
10390  _spoolss_4b
10391 ****************************************************************/
10392
10393 WERROR _spoolss_4b(struct pipes_struct *p,
10394                    struct spoolss_4b *r)
10395 {
10396         p->rng_fault_state = true;
10397         return WERR_NOT_SUPPORTED;
10398 }
10399
10400 /****************************************************************
10401  _spoolss_4c
10402 ****************************************************************/
10403
10404 WERROR _spoolss_4c(struct pipes_struct *p,
10405                    struct spoolss_4c *r)
10406 {
10407         p->rng_fault_state = true;
10408         return WERR_NOT_SUPPORTED;
10409 }
10410
10411 /****************************************************************
10412  _spoolss_53
10413 ****************************************************************/
10414
10415 WERROR _spoolss_53(struct pipes_struct *p,
10416                    struct spoolss_53 *r)
10417 {
10418         p->rng_fault_state = true;
10419         return WERR_NOT_SUPPORTED;
10420 }
10421
10422 /****************************************************************
10423  _spoolss_AddPerMachineConnection
10424 ****************************************************************/
10425
10426 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10427                                         struct spoolss_AddPerMachineConnection *r)
10428 {
10429         p->rng_fault_state = true;
10430         return WERR_NOT_SUPPORTED;
10431 }
10432
10433 /****************************************************************
10434  _spoolss_DeletePerMachineConnection
10435 ****************************************************************/
10436
10437 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10438                                            struct spoolss_DeletePerMachineConnection *r)
10439 {
10440         p->rng_fault_state = true;
10441         return WERR_NOT_SUPPORTED;
10442 }
10443
10444 /****************************************************************
10445  _spoolss_EnumPerMachineConnections
10446 ****************************************************************/
10447
10448 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10449                                           struct spoolss_EnumPerMachineConnections *r)
10450 {
10451         p->rng_fault_state = true;
10452         return WERR_NOT_SUPPORTED;
10453 }
10454
10455 /****************************************************************
10456  _spoolss_5a
10457 ****************************************************************/
10458
10459 WERROR _spoolss_5a(struct pipes_struct *p,
10460                    struct spoolss_5a *r)
10461 {
10462         p->rng_fault_state = true;
10463         return WERR_NOT_SUPPORTED;
10464 }
10465
10466 /****************************************************************
10467  _spoolss_5b
10468 ****************************************************************/
10469
10470 WERROR _spoolss_5b(struct pipes_struct *p,
10471                    struct spoolss_5b *r)
10472 {
10473         p->rng_fault_state = true;
10474         return WERR_NOT_SUPPORTED;
10475 }
10476
10477 /****************************************************************
10478  _spoolss_5c
10479 ****************************************************************/
10480
10481 WERROR _spoolss_5c(struct pipes_struct *p,
10482                    struct spoolss_5c *r)
10483 {
10484         p->rng_fault_state = true;
10485         return WERR_NOT_SUPPORTED;
10486 }
10487
10488 /****************************************************************
10489  _spoolss_5d
10490 ****************************************************************/
10491
10492 WERROR _spoolss_5d(struct pipes_struct *p,
10493                    struct spoolss_5d *r)
10494 {
10495         p->rng_fault_state = true;
10496         return WERR_NOT_SUPPORTED;
10497 }
10498
10499 /****************************************************************
10500  _spoolss_5e
10501 ****************************************************************/
10502
10503 WERROR _spoolss_5e(struct pipes_struct *p,
10504                    struct spoolss_5e *r)
10505 {
10506         p->rng_fault_state = true;
10507         return WERR_NOT_SUPPORTED;
10508 }
10509
10510 /****************************************************************
10511  _spoolss_5f
10512 ****************************************************************/
10513
10514 WERROR _spoolss_5f(struct pipes_struct *p,
10515                    struct spoolss_5f *r)
10516 {
10517         p->rng_fault_state = true;
10518         return WERR_NOT_SUPPORTED;
10519 }
10520
10521 /****************************************************************
10522  _spoolss_60
10523 ****************************************************************/
10524
10525 WERROR _spoolss_60(struct pipes_struct *p,
10526                    struct spoolss_60 *r)
10527 {
10528         p->rng_fault_state = true;
10529         return WERR_NOT_SUPPORTED;
10530 }
10531
10532 /****************************************************************
10533  _spoolss_61
10534 ****************************************************************/
10535
10536 WERROR _spoolss_61(struct pipes_struct *p,
10537                    struct spoolss_61 *r)
10538 {
10539         p->rng_fault_state = true;
10540         return WERR_NOT_SUPPORTED;
10541 }
10542
10543 /****************************************************************
10544  _spoolss_62
10545 ****************************************************************/
10546
10547 WERROR _spoolss_62(struct pipes_struct *p,
10548                    struct spoolss_62 *r)
10549 {
10550         p->rng_fault_state = true;
10551         return WERR_NOT_SUPPORTED;
10552 }
10553
10554 /****************************************************************
10555  _spoolss_63
10556 ****************************************************************/
10557
10558 WERROR _spoolss_63(struct pipes_struct *p,
10559                    struct spoolss_63 *r)
10560 {
10561         p->rng_fault_state = true;
10562         return WERR_NOT_SUPPORTED;
10563 }
10564
10565 /****************************************************************
10566  _spoolss_64
10567 ****************************************************************/
10568
10569 WERROR _spoolss_64(struct pipes_struct *p,
10570                    struct spoolss_64 *r)
10571 {
10572         p->rng_fault_state = true;
10573         return WERR_NOT_SUPPORTED;
10574 }
10575
10576 /****************************************************************
10577  _spoolss_65
10578 ****************************************************************/
10579
10580 WERROR _spoolss_65(struct pipes_struct *p,
10581                    struct spoolss_65 *r)
10582 {
10583         p->rng_fault_state = true;
10584         return WERR_NOT_SUPPORTED;
10585 }
10586
10587 /****************************************************************
10588  _spoolss_GetCorePrinterDrivers
10589 ****************************************************************/
10590
10591 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10592                                       struct spoolss_GetCorePrinterDrivers *r)
10593 {
10594         p->rng_fault_state = true;
10595         return WERR_NOT_SUPPORTED;
10596 }
10597
10598 /****************************************************************
10599  _spoolss_67
10600 ****************************************************************/
10601
10602 WERROR _spoolss_67(struct pipes_struct *p,
10603                    struct spoolss_67 *r)
10604 {
10605         p->rng_fault_state = true;
10606         return WERR_NOT_SUPPORTED;
10607 }
10608
10609 /****************************************************************
10610  _spoolss_GetPrinterDriverPackagePath
10611 ****************************************************************/
10612
10613 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10614                                             struct spoolss_GetPrinterDriverPackagePath *r)
10615 {
10616         p->rng_fault_state = true;
10617         return WERR_NOT_SUPPORTED;
10618 }
10619
10620 /****************************************************************
10621  _spoolss_69
10622 ****************************************************************/
10623
10624 WERROR _spoolss_69(struct pipes_struct *p,
10625                    struct spoolss_69 *r)
10626 {
10627         p->rng_fault_state = true;
10628         return WERR_NOT_SUPPORTED;
10629 }
10630
10631 /****************************************************************
10632  _spoolss_6a
10633 ****************************************************************/
10634
10635 WERROR _spoolss_6a(struct pipes_struct *p,
10636                    struct spoolss_6a *r)
10637 {
10638         p->rng_fault_state = true;
10639         return WERR_NOT_SUPPORTED;
10640 }
10641
10642 /****************************************************************
10643  _spoolss_6b
10644 ****************************************************************/
10645
10646 WERROR _spoolss_6b(struct pipes_struct *p,
10647                    struct spoolss_6b *r)
10648 {
10649         p->rng_fault_state = true;
10650         return WERR_NOT_SUPPORTED;
10651 }
10652
10653 /****************************************************************
10654  _spoolss_6c
10655 ****************************************************************/
10656
10657 WERROR _spoolss_6c(struct pipes_struct *p,
10658                    struct spoolss_6c *r)
10659 {
10660         p->rng_fault_state = true;
10661         return WERR_NOT_SUPPORTED;
10662 }
10663
10664 /****************************************************************
10665  _spoolss_6d
10666 ****************************************************************/
10667
10668 WERROR _spoolss_6d(struct pipes_struct *p,
10669                    struct spoolss_6d *r)
10670 {
10671         p->rng_fault_state = true;
10672         return WERR_NOT_SUPPORTED;
10673 }