s3: rpc_server needs parts of smbd.
[samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "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
51 /* macros stolen from s4 spoolss server */
52 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
53         ((info)?ndr_size_##fn(info, level, 0):0)
54
55 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
56         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
57
58 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
59         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
60
61 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
62
63 #undef DBGC_CLASS
64 #define DBGC_CLASS DBGC_RPC_SRV
65
66 #ifndef MAX_OPEN_PRINTER_EXS
67 #define MAX_OPEN_PRINTER_EXS 50
68 #endif
69
70 struct notify_back_channel;
71
72 /* structure to store the printer handles */
73 /* and a reference to what it's pointing to */
74 /* and the notify info asked about */
75 /* that's the central struct */
76 struct printer_handle {
77         struct printer_handle *prev, *next;
78         bool document_started;
79         bool page_started;
80         uint32 jobid; /* jobid in printing backend */
81         int printer_type;
82         const char *servername;
83         fstring sharename;
84         uint32 type;
85         uint32 access_granted;
86         struct {
87                 uint32 flags;
88                 uint32 options;
89                 fstring localmachine;
90                 uint32 printerlocal;
91                 struct spoolss_NotifyOption *option;
92                 struct policy_handle cli_hnd;
93                 struct notify_back_channel *cli_chan;
94                 uint32 change;
95                 /* are we in a FindNextPrinterChangeNotify() call? */
96                 bool fnpcn;
97                 struct messaging_context *msg_ctx;
98         } notify;
99         struct {
100                 fstring machine;
101                 fstring user;
102         } client;
103
104         /* devmode sent in the OpenPrinter() call */
105         struct spoolss_DeviceMode *devmode;
106
107         /* TODO cache the printer info2 structure */
108         struct spoolss_PrinterInfo2 *info2;
109
110 };
111
112 static struct printer_handle *printers_list;
113
114 struct printer_session_counter {
115         struct printer_session_counter *next;
116         struct printer_session_counter *prev;
117
118         int snum;
119         uint32_t counter;
120 };
121
122 static struct printer_session_counter *counter_list;
123
124 struct notify_back_channel {
125         struct notify_back_channel *prev, *next;
126
127         /* associated client */
128         struct sockaddr_storage client_address;
129
130         /* print notify back-channel pipe handle*/
131         struct rpc_pipe_client *cli_pipe;
132         struct dcerpc_binding_handle *binding_handle;
133         uint32_t active_connections;
134 };
135
136 static struct notify_back_channel *back_channels;
137
138 /* Map generic permissions to printer object specific permissions */
139
140 const struct standard_mapping printer_std_mapping = {
141         PRINTER_READ,
142         PRINTER_WRITE,
143         PRINTER_EXECUTE,
144         PRINTER_ALL_ACCESS
145 };
146
147 /* Map generic permissions to print server object specific permissions */
148
149 const struct standard_mapping printserver_std_mapping = {
150         SERVER_READ,
151         SERVER_WRITE,
152         SERVER_EXECUTE,
153         SERVER_ALL_ACCESS
154 };
155
156 /* API table for Xcv Monitor functions */
157
158 struct xcv_api_table {
159         const char *name;
160         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
161 };
162
163 static void prune_printername_cache(void);
164
165 /********************************************************************
166  * Canonicalize servername.
167  ********************************************************************/
168
169 static const char *canon_servername(const char *servername)
170 {
171         const char *pservername = servername;
172         while (*pservername == '\\') {
173                 pservername++;
174         }
175         return pservername;
176 }
177
178 /* translate between internal status numbers and NT status numbers */
179 static int nt_printj_status(int v)
180 {
181         switch (v) {
182         case LPQ_QUEUED:
183                 return 0;
184         case LPQ_PAUSED:
185                 return JOB_STATUS_PAUSED;
186         case LPQ_SPOOLING:
187                 return JOB_STATUS_SPOOLING;
188         case LPQ_PRINTING:
189                 return JOB_STATUS_PRINTING;
190         case LPQ_ERROR:
191                 return JOB_STATUS_ERROR;
192         case LPQ_DELETING:
193                 return JOB_STATUS_DELETING;
194         case LPQ_OFFLINE:
195                 return JOB_STATUS_OFFLINE;
196         case LPQ_PAPEROUT:
197                 return JOB_STATUS_PAPEROUT;
198         case LPQ_PRINTED:
199                 return JOB_STATUS_PRINTED;
200         case LPQ_DELETED:
201                 return JOB_STATUS_DELETED;
202         case LPQ_BLOCKED:
203                 return JOB_STATUS_BLOCKED_DEVQ;
204         case LPQ_USER_INTERVENTION:
205                 return JOB_STATUS_USER_INTERVENTION;
206         }
207         return 0;
208 }
209
210 static int nt_printq_status(int v)
211 {
212         switch (v) {
213         case LPQ_PAUSED:
214                 return PRINTER_STATUS_PAUSED;
215         case LPQ_QUEUED:
216         case LPQ_SPOOLING:
217         case LPQ_PRINTING:
218                 return 0;
219         }
220         return 0;
221 }
222
223 /***************************************************************************
224  Disconnect from the client
225 ****************************************************************************/
226
227 static void srv_spoolss_replycloseprinter(int snum,
228                                           struct printer_handle *prn_hnd)
229 {
230         WERROR result;
231         NTSTATUS status;
232
233         /*
234          * Tell the specific printing tdb we no longer want messages for this printer
235          * by deregistering our PID.
236          */
237
238         if (!print_notify_deregister_pid(snum)) {
239                 DEBUG(0, ("Failed to register our pid for printer %s\n",
240                           lp_const_servicename(snum)));
241         }
242
243         /* weird if the test succeeds !!! */
244         if (prn_hnd->notify.cli_chan == NULL ||
245             prn_hnd->notify.cli_chan->active_connections == 0) {
246                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
247                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
248                 TALLOC_FREE(prn_hnd->notify.cli_chan);
249                 return;
250         }
251
252         status = dcerpc_spoolss_ReplyClosePrinter(
253                                         prn_hnd->notify.cli_chan->binding_handle,
254                                         talloc_tos(),
255                                         &prn_hnd->notify.cli_hnd,
256                                         &result);
257         if (!NT_STATUS_IS_OK(status)) {
258                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
259                           nt_errstr(status)));
260                 result = ntstatus_to_werror(status);
261         } else if (!W_ERROR_IS_OK(result)) {
262                 DEBUG(0, ("reply_close_printer failed [%s].\n",
263                           win_errstr(result)));
264         }
265
266         /* if it's the last connection, deconnect the IPC$ share */
267         if (prn_hnd->notify.cli_chan->active_connections == 1) {
268
269                 prn_hnd->notify.cli_chan->binding_handle = NULL;
270                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
271                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
272                 TALLOC_FREE(prn_hnd->notify.cli_chan);
273
274                 if (prn_hnd->notify.msg_ctx != NULL) {
275                         messaging_deregister(prn_hnd->notify.msg_ctx,
276                                              MSG_PRINTER_NOTIFY2, NULL);
277
278                         /*
279                          * Tell the serverid.tdb we're no longer
280                          * interested in printer notify messages.
281                          */
282
283                         serverid_register_msg_flags(
284                                 messaging_server_id(prn_hnd->notify.msg_ctx),
285                                 false, FLAG_MSG_PRINT_NOTIFY);
286                 }
287         }
288
289         if (prn_hnd->notify.cli_chan) {
290                 prn_hnd->notify.cli_chan->active_connections--;
291         }
292 }
293
294 /****************************************************************************
295  Functions to free a printer entry datastruct.
296 ****************************************************************************/
297
298 static int printer_entry_destructor(struct printer_handle *Printer)
299 {
300         if (Printer->notify.cli_chan != NULL &&
301             Printer->notify.cli_chan->active_connections > 0) {
302                 int snum = -1;
303
304                 switch(Printer->printer_type) {
305                 case SPLHND_SERVER:
306                         srv_spoolss_replycloseprinter(snum, Printer);
307                         break;
308
309                 case SPLHND_PRINTER:
310                         snum = print_queue_snum(Printer->sharename);
311                         if (snum != -1) {
312                                 srv_spoolss_replycloseprinter(snum, Printer);
313                         }
314                         break;
315                 default:
316                         break;
317                 }
318         }
319
320         Printer->notify.flags=0;
321         Printer->notify.options=0;
322         Printer->notify.localmachine[0]='\0';
323         Printer->notify.printerlocal=0;
324         TALLOC_FREE(Printer->notify.option);
325         TALLOC_FREE(Printer->devmode);
326
327         /* Remove from the internal list. */
328         DLIST_REMOVE(printers_list, Printer);
329         return 0;
330 }
331
332 /****************************************************************************
333   find printer index by handle
334 ****************************************************************************/
335
336 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
337                                                         struct policy_handle *hnd)
338 {
339         struct printer_handle *find_printer = NULL;
340
341         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
342                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
343                 return NULL;
344         }
345
346         return find_printer;
347 }
348
349 /****************************************************************************
350  Close printer index by handle.
351 ****************************************************************************/
352
353 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
354 {
355         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
356
357         if (!Printer) {
358                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
359                         OUR_HANDLE(hnd)));
360                 return false;
361         }
362
363         close_policy_hnd(p, hnd);
364
365         return true;
366 }
367
368 /****************************************************************************
369  Delete a printer given a handle.
370 ****************************************************************************/
371
372 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
373                                   const char *sharename,
374                                   struct messaging_context *msg_ctx)
375 {
376         char *cmd = lp_deleteprinter_cmd();
377         char *command = NULL;
378         int ret;
379         bool is_print_op = false;
380
381         /* can't fail if we don't try */
382
383         if ( !*cmd )
384                 return WERR_OK;
385
386         command = talloc_asprintf(ctx,
387                         "%s \"%s\"",
388                         cmd, sharename);
389         if (!command) {
390                 return WERR_NOMEM;
391         }
392         if ( token )
393                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
394
395         DEBUG(10,("Running [%s]\n", command));
396
397         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
398
399         if ( is_print_op )
400                 become_root();
401
402         if ( (ret = smbrun(command, NULL)) == 0 ) {
403                 /* Tell everyone we updated smb.conf. */
404                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
405         }
406
407         if ( is_print_op )
408                 unbecome_root();
409
410         /********** END SePrintOperatorPrivlege BLOCK **********/
411
412         DEBUGADD(10,("returned [%d]\n", ret));
413
414         TALLOC_FREE(command);
415
416         if (ret != 0)
417                 return WERR_BADFID; /* What to return here? */
418
419         /* go ahead and re-read the services immediately */
420         become_root();
421         reload_services(msg_ctx, -1, false);
422         unbecome_root();
423
424         if ( lp_servicenumber( sharename ) >= 0 )
425                 return WERR_ACCESS_DENIED;
426
427         return WERR_OK;
428 }
429
430 /****************************************************************************
431  Delete a printer given a handle.
432 ****************************************************************************/
433
434 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
435 {
436         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
437         WERROR result;
438
439         if (!Printer) {
440                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
441                         OUR_HANDLE(hnd)));
442                 return WERR_BADFID;
443         }
444
445         /*
446          * It turns out that Windows allows delete printer on a handle
447          * opened by an admin user, then used on a pipe handle created
448          * by an anonymous user..... but they're working on security.... riiight !
449          * JRA.
450          */
451
452         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
453                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
454                 return WERR_ACCESS_DENIED;
455         }
456
457         /* this does not need a become root since the access check has been
458            done on the handle already */
459
460         result = winreg_delete_printer_key(p->mem_ctx,
461                                            get_session_info_system(),
462                                            p->msg_ctx,
463                                            Printer->sharename,
464                                            "");
465         if (!W_ERROR_IS_OK(result)) {
466                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
467                 return WERR_BADFID;
468         }
469
470         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
471                                      Printer->sharename, p->msg_ctx);
472         if (!W_ERROR_IS_OK(result)) {
473                 return result;
474         }
475         prune_printername_cache();
476         return WERR_OK;
477 }
478
479 /****************************************************************************
480  Return the snum of a printer corresponding to an handle.
481 ****************************************************************************/
482
483 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
484                              int *number, struct share_params **params)
485 {
486         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
487
488         if (!Printer) {
489                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
490                         OUR_HANDLE(hnd)));
491                 return false;
492         }
493
494         switch (Printer->printer_type) {
495                 case SPLHND_PRINTER:
496                         DEBUG(4,("short name:%s\n", Printer->sharename));
497                         *number = print_queue_snum(Printer->sharename);
498                         return (*number != -1);
499                 case SPLHND_SERVER:
500                         return false;
501                 default:
502                         return false;
503         }
504 }
505
506 /****************************************************************************
507  Set printer handle type.
508  Check if it's \\server or \\server\printer
509 ****************************************************************************/
510
511 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
512 {
513         DEBUG(3,("Setting printer type=%s\n", handlename));
514
515         /* it's a print server */
516         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
517                 DEBUGADD(4,("Printer is a print server\n"));
518                 Printer->printer_type = SPLHND_SERVER;
519         }
520         /* it's a printer (set_printer_hnd_name() will handle port monitors */
521         else {
522                 DEBUGADD(4,("Printer is a printer\n"));
523                 Printer->printer_type = SPLHND_PRINTER;
524         }
525
526         return true;
527 }
528
529 static void prune_printername_cache_fn(const char *key, const char *value,
530                                        time_t timeout, void *private_data)
531 {
532         gencache_del(key);
533 }
534
535 static void prune_printername_cache(void)
536 {
537         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
538 }
539
540 /****************************************************************************
541  Set printer handle name..  Accept names like \\server, \\server\printer,
542  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
543  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
544  XcvDataPort() interface.
545 ****************************************************************************/
546
547 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
548                                    const struct auth_serversupplied_info *session_info,
549                                    struct messaging_context *msg_ctx,
550                                    struct printer_handle *Printer,
551                                    const char *handlename)
552 {
553         int snum;
554         int n_services=lp_numservices();
555         char *aprinter;
556         const char *printername;
557         const char *servername = NULL;
558         fstring sname;
559         bool found = false;
560         struct spoolss_PrinterInfo2 *info2 = NULL;
561         WERROR result;
562         char *p;
563
564         /*
565          * Hopefully nobody names his printers like this. Maybe \ or ,
566          * are illegal in printer names even?
567          */
568         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
569         char *cache_key;
570         char *tmp;
571
572         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
573                 (unsigned long)strlen(handlename)));
574
575         aprinter = CONST_DISCARD(char *, handlename);
576         if ( *handlename == '\\' ) {
577                 servername = canon_servername(handlename);
578                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
579                         *aprinter = '\0';
580                         aprinter++;
581                 }
582                 if (!is_myname_or_ipaddr(servername)) {
583                         return WERR_INVALID_PRINTER_NAME;
584                 }
585                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
586                 if (Printer->servername == NULL) {
587                         return WERR_NOMEM;
588                 }
589         }
590
591         if (Printer->printer_type == SPLHND_SERVER) {
592                 return WERR_OK;
593         }
594
595         if (Printer->printer_type != SPLHND_PRINTER) {
596                 return WERR_INVALID_HANDLE;
597         }
598
599         DEBUGADD(5, ("searching for [%s]\n", aprinter));
600
601         p = strchr(aprinter, ',');
602         if (p != NULL) {
603                 char *p2 = p;
604                 p++;
605                 if (*p == ' ') {
606                         p++;
607                 }
608                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
609                         *p2 = '\0';
610                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
611                         *p2 = '\0';
612                 }
613         }
614
615         if (p) {
616                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
617         }
618
619         /* check for the Port Monitor Interface */
620         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
621                 Printer->printer_type = SPLHND_PORTMON_TCP;
622                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
623                 found = true;
624         }
625         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
626                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
627                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
628                 found = true;
629         }
630
631         /*
632          * With hundreds of printers, the "for" loop iterating all
633          * shares can be quite expensive, as it is done on every
634          * OpenPrinter. The loop maps "aprinter" to "sname", the
635          * result of which we cache in gencache.
636          */
637
638         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
639                                     aprinter);
640         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
641
642                 found = (strcmp(tmp, printer_not_found) != 0);
643                 if (!found) {
644                         DEBUG(4, ("Printer %s not found\n", aprinter));
645                         SAFE_FREE(tmp);
646                         return WERR_INVALID_PRINTER_NAME;
647                 }
648                 fstrcpy(sname, tmp);
649                 SAFE_FREE(tmp);
650         }
651
652         /* Search all sharenames first as this is easier than pulling
653            the printer_info_2 off of disk. Don't use find_service() since
654            that calls out to map_username() */
655
656         /* do another loop to look for printernames */
657         for (snum = 0; !found && snum < n_services; snum++) {
658                 const char *printer = lp_const_servicename(snum);
659
660                 /* no point going on if this is not a printer */
661                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
662                         continue;
663                 }
664
665                 /* ignore [printers] share */
666                 if (strequal(printer, "printers")) {
667                         continue;
668                 }
669
670                 fstrcpy(sname, printer);
671                 if (strequal(aprinter, printer)) {
672                         found = true;
673                         break;
674                 }
675
676                 /* no point looking up the printer object if
677                    we aren't allowing printername != sharename */
678                 if (lp_force_printername(snum)) {
679                         continue;
680                 }
681
682                 result = winreg_get_printer(mem_ctx,
683                                             session_info,
684                                             msg_ctx,
685                                             sname,
686                                             &info2);
687                 if ( !W_ERROR_IS_OK(result) ) {
688                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
689                                  sname, win_errstr(result)));
690                         continue;
691                 }
692
693                 printername = strrchr(info2->printername, '\\');
694                 if (printername == NULL) {
695                         printername = info2->printername;
696                 } else {
697                         printername++;
698                 }
699
700                 if (strequal(printername, aprinter)) {
701                         found = true;
702                         break;
703                 }
704
705                 DEBUGADD(10, ("printername: %s\n", printername));
706
707                 TALLOC_FREE(info2);
708         }
709
710         if ( !found ) {
711                 if (cache_key != NULL) {
712                         gencache_set(cache_key, printer_not_found,
713                                      time(NULL)+300);
714                         TALLOC_FREE(cache_key);
715                 }
716                 DEBUGADD(4,("Printer not found\n"));
717                 return WERR_INVALID_PRINTER_NAME;
718         }
719
720         if (cache_key != NULL) {
721                 gencache_set(cache_key, sname, time(NULL)+300);
722                 TALLOC_FREE(cache_key);
723         }
724
725         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
726
727         fstrcpy(Printer->sharename, sname);
728
729         return WERR_OK;
730 }
731
732 /****************************************************************************
733  Find first available printer slot. creates a printer handle for you.
734  ****************************************************************************/
735
736 static WERROR open_printer_hnd(struct pipes_struct *p,
737                                struct policy_handle *hnd,
738                                const char *name,
739                                uint32_t access_granted)
740 {
741         struct printer_handle *new_printer;
742         WERROR result;
743
744         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
745
746         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
747         if (new_printer == NULL) {
748                 return WERR_NOMEM;
749         }
750         talloc_set_destructor(new_printer, printer_entry_destructor);
751
752         /* This also steals the printer_handle on the policy_handle */
753         if (!create_policy_hnd(p, hnd, new_printer)) {
754                 TALLOC_FREE(new_printer);
755                 return WERR_INVALID_HANDLE;
756         }
757
758         /* Add to the internal list. */
759         DLIST_ADD(printers_list, new_printer);
760
761         new_printer->notify.option=NULL;
762
763         if (!set_printer_hnd_printertype(new_printer, name)) {
764                 close_printer_handle(p, hnd);
765                 return WERR_INVALID_HANDLE;
766         }
767
768         result = set_printer_hnd_name(p->mem_ctx,
769                                       get_session_info_system(),
770                                       p->msg_ctx,
771                                       new_printer, name);
772         if (!W_ERROR_IS_OK(result)) {
773                 close_printer_handle(p, hnd);
774                 return result;
775         }
776
777         new_printer->access_granted = access_granted;
778
779         DEBUG(5, ("%d printer handles active\n",
780                   (int)num_pipe_handles(p)));
781
782         return WERR_OK;
783 }
784
785 /***************************************************************************
786  check to see if the client motify handle is monitoring the notification
787  given by (notify_type, notify_field).
788  **************************************************************************/
789
790 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
791                                       uint16_t notify_field)
792 {
793         return true;
794 }
795
796 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
797                                 uint16_t notify_field)
798 {
799         struct spoolss_NotifyOption *option = p->notify.option;
800         uint32_t i, j;
801
802         /*
803          * Flags should always be zero when the change notify
804          * is registered by the client's spooler.  A user Win32 app
805          * might use the flags though instead of the NOTIFY_OPTION_INFO
806          * --jerry
807          */
808
809         if (!option) {
810                 return false;
811         }
812
813         if (p->notify.flags)
814                 return is_monitoring_event_flags(
815                         p->notify.flags, notify_type, notify_field);
816
817         for (i = 0; i < option->count; i++) {
818
819                 /* Check match for notify_type */
820
821                 if (option->types[i].type != notify_type)
822                         continue;
823
824                 /* Check match for field */
825
826                 for (j = 0; j < option->types[i].count; j++) {
827                         if (option->types[i].fields[j].field == notify_field) {
828                                 return true;
829                         }
830                 }
831         }
832
833         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
834                    p->servername, p->sharename, notify_type, notify_field));
835
836         return false;
837 }
838
839 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
840         _data->data.integer[0] = _integer; \
841         _data->data.integer[1] = 0;
842
843
844 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
845         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
846         if (!_data->data.string.string) {\
847                 _data->data.string.size = 0; \
848         } \
849         _data->data.string.size = strlen_m_term(_p) * 2;
850
851 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
852         _data->data.devmode.devmode = _devmode;
853
854 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
855         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
856         if (!_data->data.sd.sd) { \
857                 _data->data.sd.sd_size = 0; \
858         } \
859         _data->data.sd.sd_size = \
860                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
861
862 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
863                                    struct tm *t,
864                                    const char **pp,
865                                    uint32_t *plen)
866 {
867         struct spoolss_Time st;
868         uint32_t len = 16;
869         char *p;
870
871         if (!init_systemtime(&st, t)) {
872                 return;
873         }
874
875         p = talloc_array(mem_ctx, char, len);
876         if (!p) {
877                 return;
878         }
879
880         /*
881          * Systemtime must be linearized as a set of UINT16's.
882          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
883          */
884
885         SSVAL(p, 0, st.year);
886         SSVAL(p, 2, st.month);
887         SSVAL(p, 4, st.day_of_week);
888         SSVAL(p, 6, st.day);
889         SSVAL(p, 8, st.hour);
890         SSVAL(p, 10, st.minute);
891         SSVAL(p, 12, st.second);
892         SSVAL(p, 14, st.millisecond);
893
894         *pp = p;
895         *plen = len;
896 }
897
898 /* Convert a notification message to a struct spoolss_Notify */
899
900 static void notify_one_value(struct spoolss_notify_msg *msg,
901                              struct spoolss_Notify *data,
902                              TALLOC_CTX *mem_ctx)
903 {
904         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
905 }
906
907 static void notify_string(struct spoolss_notify_msg *msg,
908                           struct spoolss_Notify *data,
909                           TALLOC_CTX *mem_ctx)
910 {
911         /* The length of the message includes the trailing \0 */
912
913         data->data.string.size = msg->len * 2;
914         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
915         if (!data->data.string.string) {
916                 data->data.string.size = 0;
917                 return;
918         }
919 }
920
921 static void notify_system_time(struct spoolss_notify_msg *msg,
922                                struct spoolss_Notify *data,
923                                TALLOC_CTX *mem_ctx)
924 {
925         data->data.string.string = NULL;
926         data->data.string.size = 0;
927
928         if (msg->len != sizeof(time_t)) {
929                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
930                           msg->len));
931                 return;
932         }
933
934         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
935                                &data->data.string.string,
936                                &data->data.string.size);
937 }
938
939 struct notify2_message_table {
940         const char *name;
941         void (*fn)(struct spoolss_notify_msg *msg,
942                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
943 };
944
945 static struct notify2_message_table printer_notify_table[] = {
946         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
947         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
948         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
949         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
950         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
951         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
952         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
953         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
954         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
955         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
956         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
957         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
958         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
959         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
960         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
961         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
962         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
963         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
964         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
965 };
966
967 static struct notify2_message_table job_notify_table[] = {
968         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
969         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
970         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
971         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
972         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
973         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
974         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
975         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
976         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
977         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
978         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
979         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
980         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
981         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
982         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
983         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
984         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
985         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
986         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
987         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
988         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
989         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
990         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
991         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
992 };
993
994
995 /***********************************************************************
996  Allocate talloc context for container object
997  **********************************************************************/
998
999 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1000 {
1001         if ( !ctr )
1002                 return;
1003
1004         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1005
1006         return;
1007 }
1008
1009 /***********************************************************************
1010  release all allocated memory and zero out structure
1011  **********************************************************************/
1012
1013 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1014 {
1015         if ( !ctr )
1016                 return;
1017
1018         if ( ctr->ctx )
1019                 talloc_destroy(ctr->ctx);
1020
1021         ZERO_STRUCTP(ctr);
1022
1023         return;
1024 }
1025
1026 /***********************************************************************
1027  **********************************************************************/
1028
1029 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1030 {
1031         if ( !ctr )
1032                 return NULL;
1033
1034         return ctr->ctx;
1035 }
1036
1037 /***********************************************************************
1038  **********************************************************************/
1039
1040 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1041 {
1042         if ( !ctr || !ctr->msg_groups )
1043                 return NULL;
1044
1045         if ( idx >= ctr->num_groups )
1046                 return NULL;
1047
1048         return &ctr->msg_groups[idx];
1049
1050 }
1051
1052 /***********************************************************************
1053  How many groups of change messages do we have ?
1054  **********************************************************************/
1055
1056 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1057 {
1058         if ( !ctr )
1059                 return 0;
1060
1061         return ctr->num_groups;
1062 }
1063
1064 /***********************************************************************
1065  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1066  **********************************************************************/
1067
1068 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1069 {
1070         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1071         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1072         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1073         int                             i, new_slot;
1074
1075         if ( !ctr || !msg )
1076                 return 0;
1077
1078         /* loop over all groups looking for a matching printer name */
1079
1080         for ( i=0; i<ctr->num_groups; i++ ) {
1081                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1082                         break;
1083         }
1084
1085         /* add a new group? */
1086
1087         if ( i == ctr->num_groups ) {
1088                 ctr->num_groups++;
1089
1090                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1091                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1092                         return 0;
1093                 }
1094                 ctr->msg_groups = groups;
1095
1096                 /* clear the new entry and set the printer name */
1097
1098                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1099                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1100         }
1101
1102         /* add the change messages; 'i' is the correct index now regardless */
1103
1104         msg_grp = &ctr->msg_groups[i];
1105
1106         msg_grp->num_msgs++;
1107
1108         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1109                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1110                 return 0;
1111         }
1112         msg_grp->msgs = msg_list;
1113
1114         new_slot = msg_grp->num_msgs-1;
1115         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1116
1117         /* need to allocate own copy of data */
1118
1119         if ( msg->len != 0 )
1120                 msg_grp->msgs[new_slot].notify.data = (char *)
1121                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1122
1123         return ctr->num_groups;
1124 }
1125
1126 static void construct_info_data(struct spoolss_Notify *info_data,
1127                                 enum spoolss_NotifyType type,
1128                                 uint16_t field, int id);
1129
1130 /***********************************************************************
1131  Send a change notication message on all handles which have a call
1132  back registered
1133  **********************************************************************/
1134
1135 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1136                                   struct printer_handle *prn_hnd,
1137                                   SPOOLSS_NOTIFY_MSG *messages,
1138                                   uint32_t num_msgs,
1139                                   struct spoolss_Notify **_notifies,
1140                                   int *_count)
1141 {
1142         struct spoolss_Notify *notifies;
1143         SPOOLSS_NOTIFY_MSG *msg;
1144         int count = 0;
1145         uint32_t id;
1146         int i;
1147
1148         notifies = talloc_zero_array(mem_ctx,
1149                                      struct spoolss_Notify, num_msgs);
1150         if (!notifies) {
1151                 return ENOMEM;
1152         }
1153
1154         for (i = 0; i < num_msgs; i++) {
1155
1156                 msg = &messages[i];
1157
1158                 /* Are we monitoring this event? */
1159
1160                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1161                         continue;
1162                 }
1163
1164                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1165                            "for printer [%s]\n",
1166                            msg->type, msg->field, prn_hnd->sharename));
1167
1168                 /*
1169                  * if the is a printer notification handle and not a job
1170                  * notification type, then set the id to 0.
1171                  * Otherwise just use what was specified in the message.
1172                  *
1173                  * When registering change notification on a print server
1174                  * handle we always need to send back the id (snum) matching
1175                  * the printer for which the change took place.
1176                  * For change notify registered on a printer handle,
1177                  * this does not matter and the id should be 0.
1178                  *
1179                  * --jerry
1180                  */
1181
1182                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1183                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1184                         id = 0;
1185                 } else {
1186                         id = msg->id;
1187                 }
1188
1189                 /* Convert unix jobid to smb jobid */
1190
1191                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1192                         id = sysjob_to_jobid(msg->id);
1193
1194                         if (id == -1) {
1195                                 DEBUG(3, ("no such unix jobid %d\n",
1196                                           msg->id));
1197                                 continue;
1198                         }
1199                 }
1200
1201                 construct_info_data(&notifies[count],
1202                                     msg->type, msg->field, id);
1203
1204                 switch(msg->type) {
1205                 case PRINTER_NOTIFY_TYPE:
1206                         if (printer_notify_table[msg->field].fn) {
1207                                 printer_notify_table[msg->field].fn(msg,
1208                                                 &notifies[count], mem_ctx);
1209                         }
1210                         break;
1211
1212                 case JOB_NOTIFY_TYPE:
1213                         if (job_notify_table[msg->field].fn) {
1214                                 job_notify_table[msg->field].fn(msg,
1215                                                 &notifies[count], mem_ctx);
1216                         }
1217                         break;
1218
1219                 default:
1220                         DEBUG(5, ("Unknown notification type %d\n",
1221                                   msg->type));
1222                         continue;
1223                 }
1224
1225                 count++;
1226         }
1227
1228         *_notifies = notifies;
1229         *_count = count;
1230
1231         return 0;
1232 }
1233
1234 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1235                                 struct printer_handle *prn_hnd,
1236                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1237 {
1238         struct spoolss_Notify *notifies;
1239         int count = 0;
1240         union spoolss_ReplyPrinterInfo info;
1241         struct spoolss_NotifyInfo info0;
1242         uint32_t reply_result;
1243         NTSTATUS status;
1244         WERROR werr;
1245         int ret;
1246
1247         /* Is there notification on this handle? */
1248         if (prn_hnd->notify.cli_chan == NULL ||
1249             prn_hnd->notify.cli_chan->active_connections == 0) {
1250                 return 0;
1251         }
1252
1253         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1254                    prn_hnd->servername, prn_hnd->sharename));
1255
1256         /* For this printer? Print servers always receive notifications. */
1257         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1258             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1259                 return 0;
1260         }
1261
1262         DEBUG(10,("Our printer\n"));
1263
1264         /* build the array of change notifications */
1265         ret = build_notify2_messages(mem_ctx, prn_hnd,
1266                                      msg_group->msgs,
1267                                      msg_group->num_msgs,
1268                                      &notifies, &count);
1269         if (ret) {
1270                 return ret;
1271         }
1272
1273         info0.version   = 0x2;
1274         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1275         info0.count     = count;
1276         info0.notifies  = notifies;
1277
1278         info.info0 = &info0;
1279
1280         status = dcerpc_spoolss_RouterReplyPrinterEx(
1281                                 prn_hnd->notify.cli_chan->binding_handle,
1282                                 mem_ctx,
1283                                 &prn_hnd->notify.cli_hnd,
1284                                 prn_hnd->notify.change, /* color */
1285                                 prn_hnd->notify.flags,
1286                                 &reply_result,
1287                                 0, /* reply_type, must be 0 */
1288                                 info, &werr);
1289         if (!NT_STATUS_IS_OK(status)) {
1290                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1291                           "failed: %s\n",
1292                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1293                           nt_errstr(status)));
1294                 werr = ntstatus_to_werror(status);
1295         } else if (!W_ERROR_IS_OK(werr)) {
1296                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1297                           "failed: %s\n",
1298                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1299                           win_errstr(werr)));
1300         }
1301         switch (reply_result) {
1302         case 0:
1303                 break;
1304         case PRINTER_NOTIFY_INFO_DISCARDED:
1305         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1306         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1307                 break;
1308         default:
1309                 break;
1310         }
1311
1312         return 0;
1313 }
1314
1315 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1316 {
1317         struct printer_handle    *p;
1318         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1319         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1320         int ret;
1321
1322         if ( !msg_group ) {
1323                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1324                 return;
1325         }
1326
1327         if (!msg_group->msgs) {
1328                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1329                 return;
1330         }
1331
1332         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1333
1334         /* loop over all printers */
1335
1336         for (p = printers_list; p; p = p->next) {
1337                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1338                 if (ret) {
1339                         goto done;
1340                 }
1341         }
1342
1343 done:
1344         DEBUG(8,("send_notify2_changes: Exit...\n"));
1345         return;
1346 }
1347
1348 /***********************************************************************
1349  **********************************************************************/
1350
1351 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1352 {
1353
1354         uint32_t tv_sec, tv_usec;
1355         size_t offset = 0;
1356
1357         /* Unpack message */
1358
1359         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1360                              msg->printer);
1361
1362         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1363                                 &tv_sec, &tv_usec,
1364                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1365
1366         if (msg->len == 0)
1367                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1368                            &msg->notify.value[0], &msg->notify.value[1]);
1369         else
1370                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1371                            &msg->len, &msg->notify.data);
1372
1373         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1374                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1375
1376         tv->tv_sec = tv_sec;
1377         tv->tv_usec = tv_usec;
1378
1379         if (msg->len == 0)
1380                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1381                           msg->notify.value[1]));
1382         else
1383                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1384
1385         return true;
1386 }
1387
1388 /********************************************************************
1389  Receive a notify2 message list
1390  ********************************************************************/
1391
1392 static void receive_notify2_message_list(struct messaging_context *msg,
1393                                          void *private_data,
1394                                          uint32_t msg_type,
1395                                          struct server_id server_id,
1396                                          DATA_BLOB *data)
1397 {
1398         size_t                  msg_count, i;
1399         char                    *buf = (char *)data->data;
1400         char                    *msg_ptr;
1401         size_t                  msg_len;
1402         SPOOLSS_NOTIFY_MSG      notify;
1403         SPOOLSS_NOTIFY_MSG_CTR  messages;
1404         int                     num_groups;
1405
1406         if (data->length < 4) {
1407                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1408                 return;
1409         }
1410
1411         msg_count = IVAL(buf, 0);
1412         msg_ptr = buf + 4;
1413
1414         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1415
1416         if (msg_count == 0) {
1417                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1418                 return;
1419         }
1420
1421         /* initialize the container */
1422
1423         ZERO_STRUCT( messages );
1424         notify_msg_ctr_init( &messages );
1425
1426         /*
1427          * build message groups for each printer identified
1428          * in a change_notify msg.  Remember that a PCN message
1429          * includes the handle returned for the srv_spoolss_replyopenprinter()
1430          * call.  Therefore messages are grouped according to printer handle.
1431          */
1432
1433         for ( i=0; i<msg_count; i++ ) {
1434                 struct timeval msg_tv;
1435
1436                 if (msg_ptr + 4 - buf > data->length) {
1437                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1438                         return;
1439                 }
1440
1441                 msg_len = IVAL(msg_ptr,0);
1442                 msg_ptr += 4;
1443
1444                 if (msg_ptr + msg_len - buf > data->length) {
1445                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1446                         return;
1447                 }
1448
1449                 /* unpack messages */
1450
1451                 ZERO_STRUCT( notify );
1452                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1453                 msg_ptr += msg_len;
1454
1455                 /* add to correct list in container */
1456
1457                 notify_msg_ctr_addmsg( &messages, &notify );
1458
1459                 /* free memory that might have been allocated by notify2_unpack_msg() */
1460
1461                 if ( notify.len != 0 )
1462                         SAFE_FREE( notify.notify.data );
1463         }
1464
1465         /* process each group of messages */
1466
1467         num_groups = notify_msg_ctr_numgroups( &messages );
1468         for ( i=0; i<num_groups; i++ )
1469                 send_notify2_changes( &messages, i );
1470
1471
1472         /* cleanup */
1473
1474         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1475                 (uint32_t)msg_count ));
1476
1477         notify_msg_ctr_destroy( &messages );
1478
1479         return;
1480 }
1481
1482 /********************************************************************
1483  Send a message to ourself about new driver being installed
1484  so we can upgrade the information for each printer bound to this
1485  driver
1486  ********************************************************************/
1487
1488 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1489                                             struct messaging_context *msg_ctx)
1490 {
1491         int len = strlen(drivername);
1492
1493         if (!len)
1494                 return false;
1495
1496         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1497                 drivername));
1498
1499         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1500                            MSG_PRINTER_DRVUPGRADE,
1501                            (uint8_t *)drivername, len+1);
1502
1503         return true;
1504 }
1505
1506 void srv_spoolss_cleanup(void)
1507 {
1508         struct printer_session_counter *session_counter;
1509
1510         for (session_counter = counter_list;
1511              session_counter != NULL;
1512              session_counter = counter_list) {
1513                 DLIST_REMOVE(counter_list, session_counter);
1514                 TALLOC_FREE(session_counter);
1515         }
1516 }
1517
1518 /**********************************************************************
1519  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1520  over all printers, upgrading ones as necessary
1521  **********************************************************************/
1522
1523 void do_drv_upgrade_printer(struct messaging_context *msg,
1524                             void *private_data,
1525                             uint32_t msg_type,
1526                             struct server_id server_id,
1527                             DATA_BLOB *data)
1528 {
1529         TALLOC_CTX *tmp_ctx;
1530         struct auth_serversupplied_info *session_info = NULL;
1531         struct spoolss_PrinterInfo2 *pinfo2;
1532         NTSTATUS status;
1533         WERROR result;
1534         const char *drivername;
1535         int snum;
1536         int n_services = lp_numservices();
1537
1538         tmp_ctx = talloc_new(NULL);
1539         if (!tmp_ctx) return;
1540
1541         status = make_session_info_system(tmp_ctx, &session_info);
1542         if (!NT_STATUS_IS_OK(status)) {
1543                 DEBUG(0, ("do_drv_upgrade_printer: "
1544                           "Could not create system session_info\n"));
1545                 goto done;
1546         }
1547
1548         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1549         if (!drivername) {
1550                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1551                 goto done;
1552         }
1553
1554         DEBUG(10, ("do_drv_upgrade_printer: "
1555                    "Got message for new driver [%s]\n", drivername));
1556
1557         /* Iterate the printer list */
1558
1559         for (snum = 0; snum < n_services; snum++) {
1560                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1561                         continue;
1562                 }
1563
1564                 /* ignore [printers] share */
1565                 if (strequal(lp_const_servicename(snum), "printers")) {
1566                         continue;
1567                 }
1568
1569                 result = winreg_get_printer(tmp_ctx, session_info, msg,
1570                                             lp_const_servicename(snum),
1571                                             &pinfo2);
1572
1573                 if (!W_ERROR_IS_OK(result)) {
1574                         continue;
1575                 }
1576
1577                 if (!pinfo2->drivername) {
1578                         continue;
1579                 }
1580
1581                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1582                         continue;
1583                 }
1584
1585                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1586
1587                 /* all we care about currently is the change_id */
1588                 result = winreg_printer_update_changeid(tmp_ctx,
1589                                                         session_info,
1590                                                         msg,
1591                                                         pinfo2->printername);
1592
1593                 if (!W_ERROR_IS_OK(result)) {
1594                         DEBUG(3, ("do_drv_upgrade_printer: "
1595                                   "Failed to update changeid [%s]\n",
1596                                   win_errstr(result)));
1597                 }
1598         }
1599
1600         /* all done */
1601 done:
1602         talloc_free(tmp_ctx);
1603 }
1604
1605 /********************************************************************
1606  Update the cache for all printq's with a registered client
1607  connection
1608  ********************************************************************/
1609
1610 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1611 {
1612         struct printer_handle *printer = printers_list;
1613         int snum;
1614
1615         /* loop through all printers and update the cache where
1616            a client is connected */
1617         while (printer) {
1618                 if ((printer->printer_type == SPLHND_PRINTER) &&
1619                     ((printer->notify.cli_chan != NULL) &&
1620                      (printer->notify.cli_chan->active_connections > 0))) {
1621                         snum = print_queue_snum(printer->sharename);
1622                         print_queue_status(msg_ctx, snum, NULL, NULL);
1623                 }
1624
1625                 printer = printer->next;
1626         }
1627
1628         return;
1629 }
1630
1631 /****************************************************************
1632  _spoolss_OpenPrinter
1633 ****************************************************************/
1634
1635 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1636                             struct spoolss_OpenPrinter *r)
1637 {
1638         struct spoolss_OpenPrinterEx e;
1639         WERROR werr;
1640
1641         ZERO_STRUCT(e.in.userlevel);
1642
1643         e.in.printername        = r->in.printername;
1644         e.in.datatype           = r->in.datatype;
1645         e.in.devmode_ctr        = r->in.devmode_ctr;
1646         e.in.access_mask        = r->in.access_mask;
1647         e.in.level              = 0;
1648
1649         e.out.handle            = r->out.handle;
1650
1651         werr = _spoolss_OpenPrinterEx(p, &e);
1652
1653         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1654                 /* OpenPrinterEx returns this for a bad
1655                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1656                  * instead.
1657                  */
1658                 werr = WERR_INVALID_PRINTER_NAME;
1659         }
1660
1661         return werr;
1662 }
1663
1664 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1665                               struct spoolss_DeviceMode *orig,
1666                               struct spoolss_DeviceMode **dest)
1667 {
1668         struct spoolss_DeviceMode *dm;
1669
1670         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1671         if (!dm) {
1672                 return WERR_NOMEM;
1673         }
1674
1675         /* copy all values, then duplicate strings and structs */
1676         *dm = *orig;
1677
1678         dm->devicename = talloc_strdup(dm, orig->devicename);
1679         if (!dm->devicename) {
1680                 return WERR_NOMEM;
1681         }
1682         dm->formname = talloc_strdup(dm, orig->formname);
1683         if (!dm->formname) {
1684                 return WERR_NOMEM;
1685         }
1686         if (orig->driverextra_data.data) {
1687                 dm->driverextra_data.data =
1688                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1689                                         orig->driverextra_data.length);
1690                 if (!dm->driverextra_data.data) {
1691                         return WERR_NOMEM;
1692                 }
1693         }
1694
1695         *dest = dm;
1696         return WERR_OK;
1697 }
1698
1699 /****************************************************************
1700  _spoolss_OpenPrinterEx
1701 ****************************************************************/
1702
1703 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1704                               struct spoolss_OpenPrinterEx *r)
1705 {
1706         int snum;
1707         struct printer_handle *Printer=NULL;
1708         WERROR result;
1709
1710         if (!r->in.printername) {
1711                 return WERR_INVALID_PARAM;
1712         }
1713
1714         if (r->in.level > 3) {
1715                 return WERR_INVALID_PARAM;
1716         }
1717         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1718             (r->in.level == 2 && !r->in.userlevel.level2) ||
1719             (r->in.level == 3 && !r->in.userlevel.level3)) {
1720                 return WERR_INVALID_PARAM;
1721         }
1722
1723         /* some sanity check because you can open a printer or a print server */
1724         /* aka: \\server\printer or \\server */
1725
1726         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1727
1728         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1729         if (!W_ERROR_IS_OK(result)) {
1730                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1731                         "for printer %s\n", r->in.printername));
1732                 ZERO_STRUCTP(r->out.handle);
1733                 return result;
1734         }
1735
1736         Printer = find_printer_index_by_hnd(p, r->out.handle);
1737         if ( !Printer ) {
1738                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1739                         "handle we created for printer %s\n", r->in.printername));
1740                 close_printer_handle(p, r->out.handle);
1741                 ZERO_STRUCTP(r->out.handle);
1742                 return WERR_INVALID_PARAM;
1743         }
1744
1745         /*
1746          * First case: the user is opening the print server:
1747          *
1748          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1749          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1750          *
1751          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1752          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1753          * or if the user is listed in the smb.conf printer admin parameter.
1754          *
1755          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1756          * client view printer folder, but does not show the MSAPW.
1757          *
1758          * Note: this test needs code to check access rights here too. Jeremy
1759          * could you look at this?
1760          *
1761          * Second case: the user is opening a printer:
1762          * NT doesn't let us connect to a printer if the connecting user
1763          * doesn't have print permission.
1764          *
1765          * Third case: user is opening a Port Monitor
1766          * access checks same as opening a handle to the print server.
1767          */
1768
1769         switch (Printer->printer_type )
1770         {
1771         case SPLHND_SERVER:
1772         case SPLHND_PORTMON_TCP:
1773         case SPLHND_PORTMON_LOCAL:
1774                 /* Printserver handles use global struct... */
1775
1776                 snum = -1;
1777
1778                 /* Map standard access rights to object specific access rights */
1779
1780                 se_map_standard(&r->in.access_mask,
1781                                 &printserver_std_mapping);
1782
1783                 /* Deny any object specific bits that don't apply to print
1784                    servers (i.e printer and job specific bits) */
1785
1786                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1787
1788                 if (r->in.access_mask &
1789                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1790                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1791                         close_printer_handle(p, r->out.handle);
1792                         ZERO_STRUCTP(r->out.handle);
1793                         return WERR_ACCESS_DENIED;
1794                 }
1795
1796                 /* Allow admin access */
1797
1798                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1799                 {
1800                         if (!lp_ms_add_printer_wizard()) {
1801                                 close_printer_handle(p, r->out.handle);
1802                                 ZERO_STRUCTP(r->out.handle);
1803                                 return WERR_ACCESS_DENIED;
1804                         }
1805
1806                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1807                            and not a printer admin, then fail */
1808
1809                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1810                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1811                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1812                             !token_contains_name_in_list(
1813                                     uidtoname(p->session_info->utok.uid),
1814                                     p->session_info->info3->base.domain.string,
1815                                     NULL,
1816                                     p->session_info->security_token,
1817                                     lp_printer_admin(snum))) {
1818                                 close_printer_handle(p, r->out.handle);
1819                                 ZERO_STRUCTP(r->out.handle);
1820                                 DEBUG(3,("access DENIED as user is not root, "
1821                                         "has no printoperator privilege, "
1822                                         "not a member of the printoperator builtin group and "
1823                                         "is not in printer admin list"));
1824                                 return WERR_ACCESS_DENIED;
1825                         }
1826
1827                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1828                 }
1829                 else
1830                 {
1831                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1832                 }
1833
1834                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1835                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1836
1837                 /* We fall through to return WERR_OK */
1838                 break;
1839
1840         case SPLHND_PRINTER:
1841                 /* NT doesn't let us connect to a printer if the connecting user
1842                    doesn't have print permission.  */
1843
1844                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1845                         close_printer_handle(p, r->out.handle);
1846                         ZERO_STRUCTP(r->out.handle);
1847                         return WERR_BADFID;
1848                 }
1849
1850                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1851                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1852                 }
1853
1854                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1855
1856                 /* map an empty access mask to the minimum access mask */
1857                 if (r->in.access_mask == 0x0)
1858                         r->in.access_mask = PRINTER_ACCESS_USE;
1859
1860                 /*
1861                  * If we are not serving the printer driver for this printer,
1862                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1863                  * will keep NT clients happy  --jerry
1864                  */
1865
1866                 if (lp_use_client_driver(snum)
1867                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1868                 {
1869                         r->in.access_mask = PRINTER_ACCESS_USE;
1870                 }
1871
1872                 /* check smb.conf parameters and the the sec_desc */
1873
1874                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1875                                   p->client_id->name, p->client_id->addr)) {
1876                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1877                         ZERO_STRUCTP(r->out.handle);
1878                         return WERR_ACCESS_DENIED;
1879                 }
1880
1881                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1882                                    p->session_info->security_token, snum) ||
1883                     !print_access_check(p->session_info,
1884                                         p->msg_ctx,
1885                                         snum,
1886                                         r->in.access_mask)) {
1887                         DEBUG(3, ("access DENIED for printer open\n"));
1888                         close_printer_handle(p, r->out.handle);
1889                         ZERO_STRUCTP(r->out.handle);
1890                         return WERR_ACCESS_DENIED;
1891                 }
1892
1893                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1894                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1895                         close_printer_handle(p, r->out.handle);
1896                         ZERO_STRUCTP(r->out.handle);
1897                         return WERR_ACCESS_DENIED;
1898                 }
1899
1900                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1901                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1902                 else
1903                         r->in.access_mask = PRINTER_ACCESS_USE;
1904
1905                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1906                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1907
1908                 winreg_create_printer(p->mem_ctx,
1909                                       get_session_info_system(),
1910                                       p->msg_ctx,
1911                                       lp_const_servicename(snum));
1912
1913                 break;
1914
1915         default:
1916                 /* sanity check to prevent programmer error */
1917                 ZERO_STRUCTP(r->out.handle);
1918                 return WERR_BADFID;
1919         }
1920
1921         Printer->access_granted = r->in.access_mask;
1922
1923         /*
1924          * If the client sent a devmode in the OpenPrinter() call, then
1925          * save it here in case we get a job submission on this handle
1926          */
1927
1928          if ((Printer->printer_type != SPLHND_SERVER) &&
1929              r->in.devmode_ctr.devmode) {
1930                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1931                                 &Printer->devmode);
1932          }
1933
1934 #if 0   /* JERRY -- I'm doubtful this is really effective */
1935         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1936            optimization in Windows 2000 clients  --jerry */
1937
1938         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1939                 && (RA_WIN2K == get_remote_arch()) )
1940         {
1941                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1942                 sys_usleep( 500000 );
1943         }
1944 #endif
1945
1946         return WERR_OK;
1947 }
1948
1949 /****************************************************************
1950  _spoolss_ClosePrinter
1951 ****************************************************************/
1952
1953 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1954                              struct spoolss_ClosePrinter *r)
1955 {
1956         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1957
1958         if (Printer && Printer->document_started) {
1959                 struct spoolss_EndDocPrinter e;
1960
1961                 e.in.handle = r->in.handle;
1962
1963                 _spoolss_EndDocPrinter(p, &e);
1964         }
1965
1966         if (!close_printer_handle(p, r->in.handle))
1967                 return WERR_BADFID;
1968
1969         /* clear the returned printer handle.  Observed behavior
1970            from Win2k server.  Don't think this really matters.
1971            Previous code just copied the value of the closed
1972            handle.    --jerry */
1973
1974         ZERO_STRUCTP(r->out.handle);
1975
1976         return WERR_OK;
1977 }
1978
1979 /****************************************************************
1980  _spoolss_DeletePrinter
1981 ****************************************************************/
1982
1983 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1984                               struct spoolss_DeletePrinter *r)
1985 {
1986         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1987         WERROR result;
1988         int snum;
1989
1990         if (Printer && Printer->document_started) {
1991                 struct spoolss_EndDocPrinter e;
1992
1993                 e.in.handle = r->in.handle;
1994
1995                 _spoolss_EndDocPrinter(p, &e);
1996         }
1997
1998         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1999                 winreg_delete_printer_key(p->mem_ctx,
2000                                           get_session_info_system(),
2001                                           p->msg_ctx,
2002                                           lp_const_servicename(snum),
2003                                           "");
2004         }
2005
2006         result = delete_printer_handle(p, r->in.handle);
2007
2008         return result;
2009 }
2010
2011 /*******************************************************************
2012  * static function to lookup the version id corresponding to an
2013  * long architecture string
2014  ******************************************************************/
2015
2016 static const struct print_architecture_table_node archi_table[]= {
2017
2018         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2019         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2020         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2021         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2022         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2023         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2024         {"Windows x64",          SPL_ARCH_X64,          3 },
2025         {NULL,                   "",            -1 }
2026 };
2027
2028 static int get_version_id(const char *arch)
2029 {
2030         int i;
2031
2032         for (i=0; archi_table[i].long_archi != NULL; i++)
2033         {
2034                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2035                         return (archi_table[i].version);
2036         }
2037
2038         return -1;
2039 }
2040
2041 /****************************************************************
2042  _spoolss_DeletePrinterDriver
2043 ****************************************************************/
2044
2045 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2046                                     struct spoolss_DeletePrinterDriver *r)
2047 {
2048
2049         struct spoolss_DriverInfo8 *info = NULL;
2050         struct spoolss_DriverInfo8 *info_win2k = NULL;
2051         int                             version;
2052         WERROR                          status;
2053
2054         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2055            and not a printer admin, then fail */
2056
2057         if ( (p->session_info->utok.uid != sec_initial_uid())
2058              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2059                 && !token_contains_name_in_list(
2060                         uidtoname(p->session_info->utok.uid),
2061                         p->session_info->info3->base.domain.string,
2062                         NULL,
2063                         p->session_info->security_token,
2064                         lp_printer_admin(-1)) )
2065         {
2066                 return WERR_ACCESS_DENIED;
2067         }
2068
2069         /* check that we have a valid driver name first */
2070
2071         if ((version = get_version_id(r->in.architecture)) == -1)
2072                 return WERR_INVALID_ENVIRONMENT;
2073
2074         status = winreg_get_driver(p->mem_ctx,
2075                                    get_session_info_system(),
2076                                    p->msg_ctx,
2077                                    r->in.architecture, r->in.driver,
2078                                    version, &info);
2079         if (!W_ERROR_IS_OK(status)) {
2080                 /* try for Win2k driver if "Windows NT x86" */
2081
2082                 if ( version == 2 ) {
2083                         version = 3;
2084
2085                         status = winreg_get_driver(p->mem_ctx,
2086                                                    get_session_info_system(),
2087                                                    p->msg_ctx,
2088                                                    r->in.architecture,
2089                                                    r->in.driver,
2090                                                    version, &info);
2091                         if (!W_ERROR_IS_OK(status)) {
2092                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2093                                 goto done;
2094                         }
2095                 }
2096                 /* otherwise it was a failure */
2097                 else {
2098                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2099                         goto done;
2100                 }
2101
2102         }
2103
2104         if (printer_driver_in_use(p->mem_ctx,
2105                                   get_session_info_system(),
2106                                   p->msg_ctx,
2107                                   info)) {
2108                 status = WERR_PRINTER_DRIVER_IN_USE;
2109                 goto done;
2110         }
2111
2112         if (version == 2) {
2113                 status = winreg_get_driver(p->mem_ctx,
2114                                            get_session_info_system(),
2115                                            p->msg_ctx,
2116                                            r->in.architecture,
2117                                            r->in.driver, 3, &info_win2k);
2118                 if (W_ERROR_IS_OK(status)) {
2119                         /* if we get to here, we now have 2 driver info structures to remove */
2120                         /* remove the Win2k driver first*/
2121
2122                         status = winreg_del_driver(p->mem_ctx,
2123                                                    get_session_info_system(),
2124                                                    p->msg_ctx,
2125                                                    info_win2k, 3);
2126                         talloc_free(info_win2k);
2127
2128                         /* this should not have failed---if it did, report to client */
2129                         if (!W_ERROR_IS_OK(status)) {
2130                                 goto done;
2131                         }
2132                 }
2133         }
2134
2135         status = winreg_del_driver(p->mem_ctx,
2136                                    get_session_info_system(),
2137                                    p->msg_ctx,
2138                                    info, version);
2139
2140 done:
2141         talloc_free(info);
2142
2143         return status;
2144 }
2145
2146 /****************************************************************
2147  _spoolss_DeletePrinterDriverEx
2148 ****************************************************************/
2149
2150 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2151                                       struct spoolss_DeletePrinterDriverEx *r)
2152 {
2153         struct spoolss_DriverInfo8      *info = NULL;
2154         struct spoolss_DriverInfo8      *info_win2k = NULL;
2155         int                             version;
2156         bool                            delete_files;
2157         WERROR                          status;
2158
2159         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2160            and not a printer admin, then fail */
2161
2162         if ( (p->session_info->utok.uid != sec_initial_uid())
2163                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2164                 && !token_contains_name_in_list(
2165                         uidtoname(p->session_info->utok.uid),
2166                         p->session_info->info3->base.domain.string,
2167                         NULL,
2168                         p->session_info->security_token, lp_printer_admin(-1)) )
2169         {
2170                 return WERR_ACCESS_DENIED;
2171         }
2172
2173         /* check that we have a valid driver name first */
2174         if ((version = get_version_id(r->in.architecture)) == -1) {
2175                 /* this is what NT returns */
2176                 return WERR_INVALID_ENVIRONMENT;
2177         }
2178
2179         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2180                 version = r->in.version;
2181
2182         status = winreg_get_driver(p->mem_ctx,
2183                                    get_session_info_system(),
2184                                    p->msg_ctx,
2185                                    r->in.architecture,
2186                                    r->in.driver,
2187                                    version,
2188                                    &info);
2189         if (!W_ERROR_IS_OK(status)) {
2190                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2191
2192                 /*
2193                  * if the client asked for a specific version,
2194                  * or this is something other than Windows NT x86,
2195                  * then we've failed
2196                  */
2197
2198                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2199                         goto done;
2200
2201                 /* try for Win2k driver if "Windows NT x86" */
2202
2203                 version = 3;
2204                 status = winreg_get_driver(info,
2205                                            get_session_info_system(),
2206                                            p->msg_ctx,
2207                                            r->in.architecture,
2208                                            r->in.driver,
2209                                            version, &info);
2210                 if (!W_ERROR_IS_OK(status)) {
2211                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2212                         goto done;
2213                 }
2214         }
2215
2216         if (printer_driver_in_use(info,
2217                                   get_session_info_system(),
2218                                   p->msg_ctx,
2219                                   info)) {
2220                 status = WERR_PRINTER_DRIVER_IN_USE;
2221                 goto done;
2222         }
2223
2224         /*
2225          * we have a couple of cases to consider.
2226          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2227          *     then the delete should fail if **any** files overlap with
2228          *     other drivers
2229          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2230          *     non-overlapping files
2231          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2232          *     is set, the do not delete any files
2233          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2234          */
2235
2236         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2237
2238         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2239
2240         if (delete_files &&
2241             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2242             printer_driver_files_in_use(info,
2243                                         get_session_info_system(),
2244                                         p->msg_ctx,
2245                                         info)) {
2246                 /* no idea of the correct error here */
2247                 status = WERR_ACCESS_DENIED;
2248                 goto done;
2249         }
2250
2251
2252         /* also check for W32X86/3 if necessary; maybe we already have? */
2253
2254         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2255                 status = winreg_get_driver(info,
2256                                            get_session_info_system(),
2257                                            p->msg_ctx,
2258                                            r->in.architecture,
2259                                            r->in.driver, 3, &info_win2k);
2260                 if (W_ERROR_IS_OK(status)) {
2261
2262                         if (delete_files &&
2263                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2264                             printer_driver_files_in_use(info,
2265                                                         get_session_info_system(),
2266                                                         p->msg_ctx,
2267                                                         info_win2k)) {
2268                                 /* no idea of the correct error here */
2269                                 talloc_free(info_win2k);
2270                                 status = WERR_ACCESS_DENIED;
2271                                 goto done;
2272                         }
2273
2274                         /* if we get to here, we now have 2 driver info structures to remove */
2275                         /* remove the Win2k driver first*/
2276
2277                         status = winreg_del_driver(info,
2278                                                    get_session_info_system(),
2279                                                    p->msg_ctx,
2280                                                    info_win2k,
2281                                                    3);
2282
2283                         /* this should not have failed---if it did, report to client */
2284
2285                         if (!W_ERROR_IS_OK(status)) {
2286                                 goto done;
2287                         }
2288
2289                         /*
2290                          * now delete any associated files if delete_files is
2291                          * true. Even if this part failes, we return succes
2292                          * because the driver doesn not exist any more
2293                          */
2294                         if (delete_files) {
2295                                 delete_driver_files(get_session_info_system(),
2296                                                     info_win2k);
2297                         }
2298                 }
2299         }
2300
2301         status = winreg_del_driver(info,
2302                                    get_session_info_system(),
2303                                    p->msg_ctx,
2304                                    info,
2305                                    version);
2306         if (!W_ERROR_IS_OK(status)) {
2307                 goto done;
2308         }
2309
2310         /*
2311          * now delete any associated files if delete_files is
2312          * true. Even if this part failes, we return succes
2313          * because the driver doesn not exist any more
2314          */
2315         if (delete_files) {
2316                 delete_driver_files(get_session_info_system(), info);
2317         }
2318
2319 done:
2320         talloc_free(info);
2321         return status;
2322 }
2323
2324
2325 /********************************************************************
2326  GetPrinterData on a printer server Handle.
2327 ********************************************************************/
2328
2329 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2330                                             const char *value,
2331                                             enum winreg_Type *type,
2332                                             union spoolss_PrinterData *data)
2333 {
2334         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2335
2336         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2337                 *type = REG_DWORD;
2338                 data->value = 0x00;
2339                 return WERR_OK;
2340         }
2341
2342         if (!StrCaseCmp(value, "BeepEnabled")) {
2343                 *type = REG_DWORD;
2344                 data->value = 0x00;
2345                 return WERR_OK;
2346         }
2347
2348         if (!StrCaseCmp(value, "EventLog")) {
2349                 *type = REG_DWORD;
2350                 /* formally was 0x1b */
2351                 data->value = 0x00;
2352                 return WERR_OK;
2353         }
2354
2355         if (!StrCaseCmp(value, "NetPopup")) {
2356                 *type = REG_DWORD;
2357                 data->value = 0x00;
2358                 return WERR_OK;
2359         }
2360
2361         if (!StrCaseCmp(value, "MajorVersion")) {
2362                 *type = REG_DWORD;
2363
2364                 /* Windows NT 4.0 seems to not allow uploading of drivers
2365                    to a server that reports 0x3 as the MajorVersion.
2366                    need to investigate more how Win2k gets around this .
2367                    -- jerry */
2368
2369                 if (RA_WINNT == get_remote_arch()) {
2370                         data->value = 0x02;
2371                 } else {
2372                         data->value = 0x03;
2373                 }
2374
2375                 return WERR_OK;
2376         }
2377
2378         if (!StrCaseCmp(value, "MinorVersion")) {
2379                 *type = REG_DWORD;
2380                 data->value = 0x00;
2381                 return WERR_OK;
2382         }
2383
2384         /* REG_BINARY
2385          *  uint32_t size        = 0x114
2386          *  uint32_t major       = 5
2387          *  uint32_t minor       = [0|1]
2388          *  uint32_t build       = [2195|2600]
2389          *  extra unicode string = e.g. "Service Pack 3"
2390          */
2391         if (!StrCaseCmp(value, "OSVersion")) {
2392                 DATA_BLOB blob;
2393                 enum ndr_err_code ndr_err;
2394                 struct spoolss_OSVersion os;
2395
2396                 os.major                = 5;    /* Windows 2000 == 5.0 */
2397                 os.minor                = 0;
2398                 os.build                = 2195; /* build */
2399                 os.extra_string         = "";   /* leave extra string empty */
2400
2401                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2402                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2403                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2404                         return WERR_GENERAL_FAILURE;
2405                 }
2406
2407                 *type = REG_BINARY;
2408                 data->binary = blob;
2409
2410                 return WERR_OK;
2411         }
2412
2413
2414         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2415                 *type = REG_SZ;
2416
2417                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2418                 W_ERROR_HAVE_NO_MEMORY(data->string);
2419
2420                 return WERR_OK;
2421         }
2422
2423         if (!StrCaseCmp(value, "Architecture")) {
2424                 *type = REG_SZ;
2425                 data->string = talloc_strdup(mem_ctx,
2426                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2427                 W_ERROR_HAVE_NO_MEMORY(data->string);
2428
2429                 return WERR_OK;
2430         }
2431
2432         if (!StrCaseCmp(value, "DsPresent")) {
2433                 *type = REG_DWORD;
2434
2435                 /* only show the publish check box if we are a
2436                    member of a AD domain */
2437
2438                 if (lp_security() == SEC_ADS) {
2439                         data->value = 0x01;
2440                 } else {
2441                         data->value = 0x00;
2442                 }
2443                 return WERR_OK;
2444         }
2445
2446         if (!StrCaseCmp(value, "DNSMachineName")) {
2447                 const char *hostname = get_mydnsfullname();
2448
2449                 if (!hostname) {
2450                         return WERR_BADFILE;
2451                 }
2452
2453                 *type = REG_SZ;
2454                 data->string = talloc_strdup(mem_ctx, hostname);
2455                 W_ERROR_HAVE_NO_MEMORY(data->string);
2456
2457                 return WERR_OK;
2458         }
2459
2460         *type = REG_NONE;
2461
2462         return WERR_INVALID_PARAM;
2463 }
2464
2465 /****************************************************************
2466  _spoolss_GetPrinterData
2467 ****************************************************************/
2468
2469 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2470                                struct spoolss_GetPrinterData *r)
2471 {
2472         struct spoolss_GetPrinterDataEx r2;
2473
2474         r2.in.handle            = r->in.handle;
2475         r2.in.key_name          = "PrinterDriverData";
2476         r2.in.value_name        = r->in.value_name;
2477         r2.in.offered           = r->in.offered;
2478         r2.out.type             = r->out.type;
2479         r2.out.data             = r->out.data;
2480         r2.out.needed           = r->out.needed;
2481
2482         return _spoolss_GetPrinterDataEx(p, &r2);
2483 }
2484
2485 /*********************************************************
2486  Connect to the client machine.
2487 **********************************************************/
2488
2489 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2490                         struct sockaddr_storage *client_ss, const char *remote_machine)
2491 {
2492         NTSTATUS ret;
2493         struct cli_state *the_cli;
2494         struct sockaddr_storage rm_addr;
2495         char addr[INET6_ADDRSTRLEN];
2496
2497         if ( is_zero_addr(client_ss) ) {
2498                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2499                         remote_machine));
2500                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2501                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2502                         return false;
2503                 }
2504                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2505         } else {
2506                 rm_addr = *client_ss;
2507                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2508                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2509                         addr));
2510         }
2511
2512         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2513                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2514                         addr));
2515                 return false;
2516         }
2517
2518         /* setup the connection */
2519         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2520                 &rm_addr, 0, "IPC$", "IPC",
2521                 "", /* username */
2522                 "", /* domain */
2523                 "", /* password */
2524                 0, lp_client_signing());
2525
2526         if ( !NT_STATUS_IS_OK( ret ) ) {
2527                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2528                         remote_machine ));
2529                 return false;
2530         }
2531
2532         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2533                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2534                 cli_shutdown(the_cli);
2535                 return false;
2536         }
2537
2538         /*
2539          * Ok - we have an anonymous connection to the IPC$ share.
2540          * Now start the NT Domain stuff :-).
2541          */
2542
2543         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2544         if (!NT_STATUS_IS_OK(ret)) {
2545                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2546                         remote_machine, nt_errstr(ret)));
2547                 cli_shutdown(the_cli);
2548                 return false;
2549         }
2550
2551         return true;
2552 }
2553
2554 /***************************************************************************
2555  Connect to the client.
2556 ****************************************************************************/
2557
2558 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2559                                         uint32_t localprinter,
2560                                         enum winreg_Type type,
2561                                         struct policy_handle *handle,
2562                                         struct notify_back_channel **_chan,
2563                                         struct sockaddr_storage *client_ss,
2564                                         struct messaging_context *msg_ctx)
2565 {
2566         WERROR result;
2567         NTSTATUS status;
2568         struct notify_back_channel *chan;
2569
2570         for (chan = back_channels; chan; chan = chan->next) {
2571                 if (memcmp(&chan->client_address, client_ss,
2572                            sizeof(struct sockaddr_storage)) == 0) {
2573                         break;
2574                 }
2575         }
2576
2577         /*
2578          * If it's the first connection, contact the client
2579          * and connect to the IPC$ share anonymously
2580          */
2581         if (!chan) {
2582                 fstring unix_printer;
2583
2584                 /* the +2 is to strip the leading 2 backslashs */
2585                 fstrcpy(unix_printer, printer + 2);
2586
2587                 chan = talloc_zero(back_channels, struct notify_back_channel);
2588                 if (!chan) {
2589                         return false;
2590                 }
2591                 chan->client_address = *client_ss;
2592
2593                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2594                         TALLOC_FREE(chan);
2595                         return false;
2596                 }
2597                 chan->binding_handle = chan->cli_pipe->binding_handle;
2598
2599                 DLIST_ADD(back_channels, chan);
2600
2601                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2602                                    receive_notify2_message_list);
2603                 /* Tell the connections db we're now interested in printer
2604                  * notify messages. */
2605                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2606                                             true, FLAG_MSG_PRINT_NOTIFY);
2607         }
2608
2609         /*
2610          * Tell the specific printing tdb we want messages for this printer
2611          * by registering our PID.
2612          */
2613
2614         if (!print_notify_register_pid(snum)) {
2615                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2616                           printer));
2617         }
2618
2619         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2620                                                  talloc_tos(),
2621                                                  printer,
2622                                                  localprinter,
2623                                                  type,
2624                                                  0,
2625                                                  NULL,
2626                                                  handle,
2627                                                  &result);
2628         if (!NT_STATUS_IS_OK(status)) {
2629                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2630                 result = ntstatus_to_werror(status);
2631         } else if (!W_ERROR_IS_OK(result)) {
2632                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2633         }
2634
2635         chan->active_connections++;
2636         *_chan = chan;
2637
2638         return (W_ERROR_IS_OK(result));
2639 }
2640
2641 /****************************************************************
2642  ****************************************************************/
2643
2644 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2645                                                              const struct spoolss_NotifyOption *r)
2646 {
2647         struct spoolss_NotifyOption *option;
2648         uint32_t i,k;
2649
2650         if (!r) {
2651                 return NULL;
2652         }
2653
2654         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2655         if (!option) {
2656                 return NULL;
2657         }
2658
2659         *option = *r;
2660
2661         if (!option->count) {
2662                 return option;
2663         }
2664
2665         option->types = talloc_zero_array(option,
2666                 struct spoolss_NotifyOptionType, option->count);
2667         if (!option->types) {
2668                 talloc_free(option);
2669                 return NULL;
2670         }
2671
2672         for (i=0; i < option->count; i++) {
2673                 option->types[i] = r->types[i];
2674
2675                 if (option->types[i].count) {
2676                         option->types[i].fields = talloc_zero_array(option,
2677                                 union spoolss_Field, option->types[i].count);
2678                         if (!option->types[i].fields) {
2679                                 talloc_free(option);
2680                                 return NULL;
2681                         }
2682                         for (k=0; k<option->types[i].count; k++) {
2683                                 option->types[i].fields[k] =
2684                                         r->types[i].fields[k];
2685                         }
2686                 }
2687         }
2688
2689         return option;
2690 }
2691
2692 /****************************************************************
2693  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2694  *
2695  * before replying OK: status=0 a rpc call is made to the workstation
2696  * asking ReplyOpenPrinter
2697  *
2698  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2699  * called from api_spoolss_rffpcnex
2700 ****************************************************************/
2701
2702 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2703                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2704 {
2705         int snum = -1;
2706         struct spoolss_NotifyOption *option = r->in.notify_options;
2707         struct sockaddr_storage client_ss;
2708
2709         /* store the notify value in the printer struct */
2710
2711         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2712
2713         if (!Printer) {
2714                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2715                         "Invalid handle (%s:%u:%u).\n",
2716                         OUR_HANDLE(r->in.handle)));
2717                 return WERR_BADFID;
2718         }
2719
2720         Printer->notify.flags           = r->in.flags;
2721         Printer->notify.options         = r->in.options;
2722         Printer->notify.printerlocal    = r->in.printer_local;
2723         Printer->notify.msg_ctx         = p->msg_ctx;
2724
2725         TALLOC_FREE(Printer->notify.option);
2726         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2727
2728         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2729
2730         /* Connect to the client machine and send a ReplyOpenPrinter */
2731
2732         if ( Printer->printer_type == SPLHND_SERVER)
2733                 snum = -1;
2734         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2735                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2736                 return WERR_BADFID;
2737
2738         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2739                 "client_address is %s\n", p->client_id->addr));
2740
2741         if (!lp_print_notify_backchannel(snum)) {
2742                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2743                         "backchannel disabled\n"));
2744                 return WERR_SERVER_UNAVAILABLE;
2745         }
2746
2747         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2748                                    AI_NUMERICHOST)) {
2749                 return WERR_SERVER_UNAVAILABLE;
2750         }
2751
2752         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2753                                         Printer->notify.printerlocal, REG_SZ,
2754                                         &Printer->notify.cli_hnd,
2755                                         &Printer->notify.cli_chan,
2756                                         &client_ss, p->msg_ctx)) {
2757                 return WERR_SERVER_UNAVAILABLE;
2758         }
2759
2760         return WERR_OK;
2761 }
2762
2763 /*******************************************************************
2764  * fill a notify_info_data with the servername
2765  ********************************************************************/
2766
2767 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2768                                        int snum,
2769                                        struct spoolss_Notify *data,
2770                                        print_queue_struct *queue,
2771                                        struct spoolss_PrinterInfo2 *pinfo2,
2772                                        TALLOC_CTX *mem_ctx)
2773 {
2774         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2775 }
2776
2777 /*******************************************************************
2778  * fill a notify_info_data with the printername (not including the servername).
2779  ********************************************************************/
2780
2781 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2782                                         int snum,
2783                                         struct spoolss_Notify *data,
2784                                         print_queue_struct *queue,
2785                                         struct spoolss_PrinterInfo2 *pinfo2,
2786                                         TALLOC_CTX *mem_ctx)
2787 {
2788         /* the notify name should not contain the \\server\ part */
2789         const char *p = strrchr(pinfo2->printername, '\\');
2790
2791         if (!p) {
2792                 p = pinfo2->printername;
2793         } else {
2794                 p++;
2795         }
2796
2797         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2798 }
2799
2800 /*******************************************************************
2801  * fill a notify_info_data with the servicename
2802  ********************************************************************/
2803
2804 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2805                                       int snum,
2806                                       struct spoolss_Notify *data,
2807                                       print_queue_struct *queue,
2808                                       struct spoolss_PrinterInfo2 *pinfo2,
2809                                       TALLOC_CTX *mem_ctx)
2810 {
2811         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2812 }
2813
2814 /*******************************************************************
2815  * fill a notify_info_data with the port name
2816  ********************************************************************/
2817
2818 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2819                                      int snum,
2820                                      struct spoolss_Notify *data,
2821                                      print_queue_struct *queue,
2822                                      struct spoolss_PrinterInfo2 *pinfo2,
2823                                      TALLOC_CTX *mem_ctx)
2824 {
2825         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2826 }
2827
2828 /*******************************************************************
2829  * fill a notify_info_data with the printername
2830  * but it doesn't exist, have to see what to do
2831  ********************************************************************/
2832
2833 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2834                                        int snum,
2835                                        struct spoolss_Notify *data,
2836                                        print_queue_struct *queue,
2837                                        struct spoolss_PrinterInfo2 *pinfo2,
2838                                        TALLOC_CTX *mem_ctx)
2839 {
2840         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2841 }
2842
2843 /*******************************************************************
2844  * fill a notify_info_data with the comment
2845  ********************************************************************/
2846
2847 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2848                                    int snum,
2849                                    struct spoolss_Notify *data,
2850                                    print_queue_struct *queue,
2851                                    struct spoolss_PrinterInfo2 *pinfo2,
2852                                    TALLOC_CTX *mem_ctx)
2853 {
2854         const char *p;
2855
2856         if (*pinfo2->comment == '\0') {
2857                 p = lp_comment(snum);
2858         } else {
2859                 p = pinfo2->comment;
2860         }
2861
2862         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2863 }
2864
2865 /*******************************************************************
2866  * fill a notify_info_data with the comment
2867  * location = "Room 1, floor 2, building 3"
2868  ********************************************************************/
2869
2870 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2871                                     int snum,
2872                                     struct spoolss_Notify *data,
2873                                     print_queue_struct *queue,
2874                                     struct spoolss_PrinterInfo2 *pinfo2,
2875                                     TALLOC_CTX *mem_ctx)
2876 {
2877         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2878 }
2879
2880 /*******************************************************************
2881  * fill a notify_info_data with the device mode
2882  * jfm:xxxx don't to it for know but that's a real problem !!!
2883  ********************************************************************/
2884
2885 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2886                                    int snum,
2887                                    struct spoolss_Notify *data,
2888                                    print_queue_struct *queue,
2889                                    struct spoolss_PrinterInfo2 *pinfo2,
2890                                    TALLOC_CTX *mem_ctx)
2891 {
2892         /* for a dummy implementation we have to zero the fields */
2893         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2894 }
2895
2896 /*******************************************************************
2897  * fill a notify_info_data with the separator file name
2898  ********************************************************************/
2899
2900 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2901                                    int snum,
2902                                    struct spoolss_Notify *data,
2903                                    print_queue_struct *queue,
2904                                    struct spoolss_PrinterInfo2 *pinfo2,
2905                                    TALLOC_CTX *mem_ctx)
2906 {
2907         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2908 }
2909
2910 /*******************************************************************
2911  * fill a notify_info_data with the print processor
2912  * jfm:xxxx return always winprint to indicate we don't do anything to it
2913  ********************************************************************/
2914
2915 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2916                                            int snum,
2917                                            struct spoolss_Notify *data,
2918                                            print_queue_struct *queue,
2919                                            struct spoolss_PrinterInfo2 *pinfo2,
2920                                            TALLOC_CTX *mem_ctx)
2921 {
2922         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2923 }
2924
2925 /*******************************************************************
2926  * fill a notify_info_data with the print processor options
2927  * jfm:xxxx send an empty string
2928  ********************************************************************/
2929
2930 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2931                                       int snum,
2932                                       struct spoolss_Notify *data,
2933                                       print_queue_struct *queue,
2934                                       struct spoolss_PrinterInfo2 *pinfo2,
2935                                       TALLOC_CTX *mem_ctx)
2936 {
2937         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2938 }
2939
2940 /*******************************************************************
2941  * fill a notify_info_data with the data type
2942  * jfm:xxxx always send RAW as data type
2943  ********************************************************************/
2944
2945 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2946                                     int snum,
2947                                     struct spoolss_Notify *data,
2948                                     print_queue_struct *queue,
2949                                     struct spoolss_PrinterInfo2 *pinfo2,
2950                                     TALLOC_CTX *mem_ctx)
2951 {
2952         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2953 }
2954
2955 /*******************************************************************
2956  * fill a notify_info_data with the security descriptor
2957  * jfm:xxxx send an null pointer to say no security desc
2958  * have to implement security before !
2959  ********************************************************************/
2960
2961 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2962                                          int snum,
2963                                          struct spoolss_Notify *data,
2964                                          print_queue_struct *queue,
2965                                          struct spoolss_PrinterInfo2 *pinfo2,
2966                                          TALLOC_CTX *mem_ctx)
2967 {
2968         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2969 }
2970
2971 /*******************************************************************
2972  * fill a notify_info_data with the attributes
2973  * jfm:xxxx a samba printer is always shared
2974  ********************************************************************/
2975
2976 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2977                                       int snum,
2978                                       struct spoolss_Notify *data,
2979                                       print_queue_struct *queue,
2980                                       struct spoolss_PrinterInfo2 *pinfo2,
2981                                       TALLOC_CTX *mem_ctx)
2982 {
2983         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2984 }
2985
2986 /*******************************************************************
2987  * fill a notify_info_data with the priority
2988  ********************************************************************/
2989
2990 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2991                                     int snum,
2992                                     struct spoolss_Notify *data,
2993                                     print_queue_struct *queue,
2994                                     struct spoolss_PrinterInfo2 *pinfo2,
2995                                     TALLOC_CTX *mem_ctx)
2996 {
2997         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2998 }
2999
3000 /*******************************************************************
3001  * fill a notify_info_data with the default priority
3002  ********************************************************************/
3003
3004 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3005                                             int snum,
3006                                             struct spoolss_Notify *data,
3007                                             print_queue_struct *queue,
3008                                             struct spoolss_PrinterInfo2 *pinfo2,
3009                                             TALLOC_CTX *mem_ctx)
3010 {
3011         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3012 }
3013
3014 /*******************************************************************
3015  * fill a notify_info_data with the start time
3016  ********************************************************************/
3017
3018 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3019                                       int snum,
3020                                       struct spoolss_Notify *data,
3021                                       print_queue_struct *queue,
3022                                       struct spoolss_PrinterInfo2 *pinfo2,
3023                                       TALLOC_CTX *mem_ctx)
3024 {
3025         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3026 }
3027
3028 /*******************************************************************
3029  * fill a notify_info_data with the until time
3030  ********************************************************************/
3031
3032 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3033                                       int snum,
3034                                       struct spoolss_Notify *data,
3035                                       print_queue_struct *queue,
3036                                       struct spoolss_PrinterInfo2 *pinfo2,
3037                                       TALLOC_CTX *mem_ctx)
3038 {
3039         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3040 }
3041
3042 /*******************************************************************
3043  * fill a notify_info_data with the status
3044  ********************************************************************/
3045
3046 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3047                                   int snum,
3048                                   struct spoolss_Notify *data,
3049                                   print_queue_struct *queue,
3050                                   struct spoolss_PrinterInfo2 *pinfo2,
3051                                   TALLOC_CTX *mem_ctx)
3052 {
3053         print_status_struct status;
3054
3055         print_queue_length(msg_ctx, snum, &status);
3056         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3057 }
3058
3059 /*******************************************************************
3060  * fill a notify_info_data with the number of jobs queued
3061  ********************************************************************/
3062
3063 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3064                                  int snum,
3065                                  struct spoolss_Notify *data,
3066                                  print_queue_struct *queue,
3067                                  struct spoolss_PrinterInfo2 *pinfo2,
3068                                  TALLOC_CTX *mem_ctx)
3069 {
3070         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3071                 data, print_queue_length(msg_ctx, snum, NULL));
3072 }
3073
3074 /*******************************************************************
3075  * fill a notify_info_data with the average ppm
3076  ********************************************************************/
3077
3078 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3079                                        int snum,
3080                                        struct spoolss_Notify *data,
3081                                        print_queue_struct *queue,
3082                                        struct spoolss_PrinterInfo2 *pinfo2,
3083                                        TALLOC_CTX *mem_ctx)
3084 {
3085         /* always respond 8 pages per minutes */
3086         /* a little hard ! */
3087         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3088 }
3089
3090 /*******************************************************************
3091  * fill a notify_info_data with username
3092  ********************************************************************/
3093
3094 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3095                                     int snum,
3096                                     struct spoolss_Notify *data,
3097                                     print_queue_struct *queue,
3098                                     struct spoolss_PrinterInfo2 *pinfo2,
3099                                     TALLOC_CTX *mem_ctx)
3100 {
3101         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3102 }
3103
3104 /*******************************************************************
3105  * fill a notify_info_data with job status
3106  ********************************************************************/
3107
3108 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3109                                       int snum,
3110                                       struct spoolss_Notify *data,
3111                                       print_queue_struct *queue,
3112                                       struct spoolss_PrinterInfo2 *pinfo2,
3113                                       TALLOC_CTX *mem_ctx)
3114 {
3115         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3116 }
3117
3118 /*******************************************************************
3119  * fill a notify_info_data with job name
3120  ********************************************************************/
3121
3122 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3123                                     int snum,
3124                                     struct spoolss_Notify *data,
3125                                     print_queue_struct *queue,
3126                                     struct spoolss_PrinterInfo2 *pinfo2,
3127                                     TALLOC_CTX *mem_ctx)
3128 {
3129         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3130 }
3131
3132 /*******************************************************************
3133  * fill a notify_info_data with job status
3134  ********************************************************************/
3135
3136 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3137                                              int snum,
3138                                              struct spoolss_Notify *data,
3139                                              print_queue_struct *queue,
3140                                              struct spoolss_PrinterInfo2 *pinfo2,
3141                                              TALLOC_CTX *mem_ctx)
3142 {
3143         /*
3144          * Now we're returning job status codes we just return a "" here. JRA.
3145          */
3146
3147         const char *p = "";
3148
3149 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3150         p = "unknown";
3151
3152         switch (queue->status) {
3153         case LPQ_QUEUED:
3154                 p = "Queued";
3155                 break;
3156         case LPQ_PAUSED:
3157                 p = "";    /* NT provides the paused string */
3158                 break;
3159         case LPQ_SPOOLING:
3160                 p = "Spooling";
3161                 break;
3162         case LPQ_PRINTING:
3163                 p = "Printing";
3164                 break;
3165         }
3166 #endif /* NO LONGER NEEDED. */
3167
3168         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3169 }
3170
3171 /*******************************************************************
3172  * fill a notify_info_data with job time
3173  ********************************************************************/
3174
3175 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3176                                     int snum,
3177                                     struct spoolss_Notify *data,
3178                                     print_queue_struct *queue,
3179                                     struct spoolss_PrinterInfo2 *pinfo2,
3180                                     TALLOC_CTX *mem_ctx)
3181 {
3182         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3183 }
3184
3185 /*******************************************************************
3186  * fill a notify_info_data with job size
3187  ********************************************************************/
3188
3189 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3190                                     int snum,
3191                                     struct spoolss_Notify *data,
3192                                     print_queue_struct *queue,
3193                                     struct spoolss_PrinterInfo2 *pinfo2,
3194                                     TALLOC_CTX *mem_ctx)
3195 {
3196         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3197 }
3198
3199 /*******************************************************************
3200  * fill a notify_info_data with page info
3201  ********************************************************************/
3202 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3203                                        int snum,
3204                                 struct spoolss_Notify *data,
3205                                 print_queue_struct *queue,
3206                                 struct spoolss_PrinterInfo2 *pinfo2,
3207                                 TALLOC_CTX *mem_ctx)
3208 {
3209         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3210 }
3211
3212 /*******************************************************************
3213  * fill a notify_info_data with pages printed info.
3214  ********************************************************************/
3215 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3216                                          int snum,
3217                                 struct spoolss_Notify *data,
3218                                 print_queue_struct *queue,
3219                                 struct spoolss_PrinterInfo2 *pinfo2,
3220                                 TALLOC_CTX *mem_ctx)
3221 {
3222         /* Add code when back-end tracks this */
3223         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3224 }
3225
3226 /*******************************************************************
3227  Fill a notify_info_data with job position.
3228  ********************************************************************/
3229
3230 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3231                                         int snum,
3232                                         struct spoolss_Notify *data,
3233                                         print_queue_struct *queue,
3234                                         struct spoolss_PrinterInfo2 *pinfo2,
3235                                         TALLOC_CTX *mem_ctx)
3236 {
3237         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3238 }
3239
3240 /*******************************************************************
3241  Fill a notify_info_data with submitted time.
3242  ********************************************************************/
3243
3244 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3245                                           int snum,
3246                                           struct spoolss_Notify *data,
3247                                           print_queue_struct *queue,
3248                                           struct spoolss_PrinterInfo2 *pinfo2,
3249                                           TALLOC_CTX *mem_ctx)
3250 {
3251         data->data.string.string = NULL;
3252         data->data.string.size = 0;
3253
3254         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3255                                &data->data.string.string,
3256                                &data->data.string.size);
3257
3258 }
3259
3260 struct s_notify_info_data_table
3261 {
3262         enum spoolss_NotifyType type;
3263         uint16_t field;
3264         const char *name;
3265         enum spoolss_NotifyTable variable_type;
3266         void (*fn) (struct messaging_context *msg_ctx,
3267                     int snum, struct spoolss_Notify *data,
3268                     print_queue_struct *queue,
3269                     struct spoolss_PrinterInfo2 *pinfo2,
3270                     TALLOC_CTX *mem_ctx);
3271 };
3272
3273 /* A table describing the various print notification constants and
3274    whether the notification data is a pointer to a variable sized
3275    buffer, a one value uint32_t or a two value uint32_t. */
3276
3277 static const struct s_notify_info_data_table notify_info_data_table[] =
3278 {
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3305 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3306 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3316 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3317 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3318 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3319 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3320 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3321 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3322 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3323 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3324 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3325 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3326 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3327 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3328 };
3329
3330 /*******************************************************************
3331  Return the variable_type of info_data structure.
3332 ********************************************************************/
3333
3334 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3335                                                                   uint16_t field)
3336 {
3337         int i=0;
3338
3339         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3340                 if ( (notify_info_data_table[i].type == type) &&
3341                      (notify_info_data_table[i].field == field) ) {
3342                         return notify_info_data_table[i].variable_type;
3343                 }
3344         }
3345
3346         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3347
3348         return (enum spoolss_NotifyTable) 0;
3349 }
3350
3351 /****************************************************************************
3352 ****************************************************************************/
3353
3354 static bool search_notify(enum spoolss_NotifyType type,
3355                           uint16_t field,
3356                           int *value)
3357 {
3358         int i;
3359
3360         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3361                 if (notify_info_data_table[i].type == type &&
3362                     notify_info_data_table[i].field == field &&
3363                     notify_info_data_table[i].fn != NULL) {
3364                         *value = i;
3365                         return true;
3366                 }
3367         }
3368
3369         return false;
3370 }
3371
3372 /****************************************************************************
3373 ****************************************************************************/
3374
3375 static void construct_info_data(struct spoolss_Notify *info_data,
3376                                 enum spoolss_NotifyType type,
3377                                 uint16_t field, int id)
3378 {
3379         info_data->type                 = type;
3380         info_data->field.field          = field;
3381         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3382         info_data->job_id               = id;
3383 }
3384
3385 /*******************************************************************
3386  *
3387  * fill a notify_info struct with info asked
3388  *
3389  ********************************************************************/
3390
3391 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3392                                           struct printer_handle *print_hnd,
3393                                           struct spoolss_NotifyInfo *info,
3394                                           struct spoolss_PrinterInfo2 *pinfo2,
3395                                           int snum,
3396                                           const struct spoolss_NotifyOptionType *option_type,
3397                                           uint32_t id,
3398                                           TALLOC_CTX *mem_ctx)
3399 {
3400         int field_num,j;
3401         enum spoolss_NotifyType type;
3402         uint16_t field;
3403
3404         struct spoolss_Notify *current_data;
3405         print_queue_struct *queue=NULL;
3406
3407         type = option_type->type;
3408
3409         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3410                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3411                 option_type->count, lp_servicename(snum)));
3412
3413         for(field_num=0; field_num < option_type->count; field_num++) {
3414                 field = option_type->fields[field_num].field;
3415
3416                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3417
3418                 if (!search_notify(type, field, &j) )
3419                         continue;
3420
3421                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3422                                                       struct spoolss_Notify,
3423                                                       info->count + 1);
3424                 if (info->notifies == NULL) {
3425                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3426                         return false;
3427                 }
3428
3429                 current_data = &info->notifies[info->count];
3430
3431                 construct_info_data(current_data, type, field, id);
3432
3433                 DEBUG(10, ("construct_notify_printer_info: "
3434                            "calling [%s]  snum=%d  printername=[%s])\n",
3435                            notify_info_data_table[j].name, snum,
3436                            pinfo2->printername));
3437
3438                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3439                                              queue, pinfo2, mem_ctx);
3440
3441                 info->count++;
3442         }
3443
3444         return true;
3445 }
3446
3447 /*******************************************************************
3448  *
3449  * fill a notify_info struct with info asked
3450  *
3451  ********************************************************************/
3452
3453 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3454                                        print_queue_struct *queue,
3455                                        struct spoolss_NotifyInfo *info,
3456                                        struct spoolss_PrinterInfo2 *pinfo2,
3457                                        int snum,
3458                                        const struct spoolss_NotifyOptionType *option_type,
3459                                        uint32_t id,
3460                                        TALLOC_CTX *mem_ctx)
3461 {
3462         int field_num,j;
3463         enum spoolss_NotifyType type;
3464         uint16_t field;
3465         struct spoolss_Notify *current_data;
3466
3467         DEBUG(4,("construct_notify_jobs_info\n"));
3468
3469         type = option_type->type;
3470
3471         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3472                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3473                 option_type->count));
3474
3475         for(field_num=0; field_num<option_type->count; field_num++) {
3476                 field = option_type->fields[field_num].field;
3477
3478                 if (!search_notify(type, field, &j) )
3479                         continue;
3480
3481                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3482                                                       struct spoolss_Notify,
3483                                                       info->count + 1);
3484                 if (info->notifies == NULL) {
3485                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3486                         return false;
3487                 }
3488
3489                 current_data=&(info->notifies[info->count]);
3490
3491                 construct_info_data(current_data, type, field, id);
3492                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3493                                              queue, pinfo2, mem_ctx);
3494                 info->count++;
3495         }
3496
3497         return true;
3498 }
3499
3500 /*
3501  * JFM: The enumeration is not that simple, it's even non obvious.
3502  *
3503  * let's take an example: I want to monitor the PRINTER SERVER for
3504  * the printer's name and the number of jobs currently queued.
3505  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3506  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3507  *
3508  * I have 3 printers on the back of my server.
3509  *
3510  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3511  * structures.
3512  *   Number     Data                    Id
3513  *      1       printer 1 name          1
3514  *      2       printer 1 cjob          1
3515  *      3       printer 2 name          2
3516  *      4       printer 2 cjob          2
3517  *      5       printer 3 name          3
3518  *      6       printer 3 name          3
3519  *
3520  * that's the print server case, the printer case is even worse.
3521  */
3522
3523 /*******************************************************************
3524  *
3525  * enumerate all printers on the printserver
3526  * fill a notify_info struct with info asked
3527  *
3528  ********************************************************************/
3529
3530 static WERROR printserver_notify_info(struct pipes_struct *p,
3531                                       struct policy_handle *hnd,
3532                                       struct spoolss_NotifyInfo *info,
3533                                       TALLOC_CTX *mem_ctx)
3534 {
3535         int snum;
3536         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3537         int n_services=lp_numservices();
3538         int i;
3539         struct spoolss_NotifyOption *option;
3540         struct spoolss_NotifyOptionType option_type;
3541         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3542         WERROR result;
3543
3544         DEBUG(4,("printserver_notify_info\n"));
3545
3546         if (!Printer)
3547                 return WERR_BADFID;
3548
3549         option = Printer->notify.option;
3550
3551         info->version   = 2;
3552         info->notifies  = NULL;
3553         info->count     = 0;
3554
3555         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3556            sending a ffpcn() request first */
3557
3558         if ( !option )
3559                 return WERR_BADFID;
3560
3561         for (i=0; i<option->count; i++) {
3562                 option_type = option->types[i];
3563
3564                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3565                         continue;
3566
3567                 for (snum = 0; snum < n_services; snum++) {
3568                         if (!lp_browseable(snum) ||
3569                             !lp_snum_ok(snum) ||
3570                             !lp_print_ok(snum)) {
3571                                 continue; /* skip */
3572                         }
3573
3574                         /* Maybe we should use the SYSTEM session_info here... */
3575                         result = winreg_get_printer(mem_ctx,
3576                                                     get_session_info_system(),
3577                                                     p->msg_ctx,
3578                                                     lp_servicename(snum),
3579                                                     &pinfo2);
3580                         if (!W_ERROR_IS_OK(result)) {
3581                                 DEBUG(4, ("printserver_notify_info: "
3582                                           "Failed to get printer [%s]\n",
3583                                           lp_servicename(snum)));
3584                                 continue;
3585                         }
3586
3587
3588                         construct_notify_printer_info(p->msg_ctx,
3589                                                       Printer, info,
3590                                                       pinfo2, snum,
3591                                                       &option_type, snum,
3592                                                       mem_ctx);
3593
3594                         TALLOC_FREE(pinfo2);
3595                 }
3596         }
3597
3598 #if 0
3599         /*
3600          * Debugging information, don't delete.
3601          */
3602
3603         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3604         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3605         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3606
3607         for (i=0; i<info->count; i++) {
3608                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3609                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3610                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3611         }
3612 #endif
3613
3614         return WERR_OK;
3615 }
3616
3617 /*******************************************************************
3618  *
3619  * fill a notify_info struct with info asked
3620  *
3621  ********************************************************************/
3622
3623 static WERROR printer_notify_info(struct pipes_struct *p,
3624                                   struct policy_handle *hnd,
3625                                   struct spoolss_NotifyInfo *info,
3626                                   TALLOC_CTX *mem_ctx)
3627 {
3628         int snum;
3629         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3630         int i;
3631         uint32_t id;
3632         struct spoolss_NotifyOption *option;
3633         struct spoolss_NotifyOptionType option_type;
3634         int count,j;
3635         print_queue_struct *queue=NULL;
3636         print_status_struct status;
3637         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3638         WERROR result;
3639
3640         DEBUG(4,("printer_notify_info\n"));
3641
3642         if (!Printer)
3643                 return WERR_BADFID;
3644
3645         option = Printer->notify.option;
3646         id = 0x0;
3647
3648         info->version   = 2;
3649         info->notifies  = NULL;
3650         info->count     = 0;
3651
3652         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3653            sending a ffpcn() request first */
3654
3655         if ( !option )
3656                 return WERR_BADFID;
3657
3658         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3659                 return WERR_BADFID;
3660         }
3661
3662         /* Maybe we should use the SYSTEM session_info here... */
3663         result = winreg_get_printer(mem_ctx,
3664                                     get_session_info_system(),
3665                                     p->msg_ctx,
3666                                     lp_servicename(snum), &pinfo2);
3667         if (!W_ERROR_IS_OK(result)) {
3668                 return WERR_BADFID;
3669         }
3670
3671         for (i=0; i<option->count; i++) {
3672                 option_type = option->types[i];
3673
3674                 switch (option_type.type) {
3675                 case PRINTER_NOTIFY_TYPE:
3676                         if (construct_notify_printer_info(p->msg_ctx,
3677                                                           Printer, info,
3678                                                           pinfo2, snum,
3679                                                           &option_type, id,
3680                                                           mem_ctx)) {
3681                                 id--;
3682                         }
3683                         break;
3684
3685                 case JOB_NOTIFY_TYPE:
3686
3687                         count = print_queue_status(p->msg_ctx, snum, &queue,
3688                                                    &status);
3689
3690                         for (j=0; j<count; j++) {
3691                                 construct_notify_jobs_info(p->msg_ctx,
3692                                                            &queue[j], info,
3693                                                            pinfo2, snum,
3694                                                            &option_type,
3695                                                            queue[j].job,
3696                                                            mem_ctx);
3697                         }
3698
3699                         SAFE_FREE(queue);
3700                         break;
3701                 }
3702         }
3703
3704         /*
3705          * Debugging information, don't delete.
3706          */
3707         /*
3708         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3709         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3710         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3711
3712         for (i=0; i<info->count; i++) {
3713                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3714                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3715                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3716         }
3717         */
3718
3719         talloc_free(pinfo2);
3720         return WERR_OK;
3721 }
3722
3723 /****************************************************************
3724  _spoolss_RouterRefreshPrinterChangeNotify
3725 ****************************************************************/
3726
3727 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3728                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3729 {
3730         struct spoolss_NotifyInfo *info;
3731
3732         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3733         WERROR result = WERR_BADFID;
3734
3735         /* we always have a spoolss_NotifyInfo struct */
3736         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3737         if (!info) {
3738                 result = WERR_NOMEM;
3739                 goto done;
3740         }
3741
3742         *r->out.info = info;
3743
3744         if (!Printer) {
3745                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3746                         "Invalid handle (%s:%u:%u).\n",
3747                         OUR_HANDLE(r->in.handle)));
3748                 goto done;
3749         }
3750
3751         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3752
3753         /*
3754          *      We are now using the change value, and
3755          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3756          *      I don't have a global notification system, I'm sending back all the
3757          *      information even when _NOTHING_ has changed.
3758          */
3759
3760         /* We need to keep track of the change value to send back in
3761            RRPCN replies otherwise our updates are ignored. */
3762
3763         Printer->notify.fnpcn = true;
3764
3765         if (Printer->notify.cli_chan != NULL &&
3766             Printer->notify.cli_chan->active_connections > 0) {
3767                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3768                         "Saving change value in request [%x]\n",
3769                         r->in.change_low));
3770                 Printer->notify.change = r->in.change_low;
3771         }
3772
3773         /* just ignore the spoolss_NotifyOption */
3774
3775         switch (Printer->printer_type) {
3776                 case SPLHND_SERVER:
3777                         result = printserver_notify_info(p, r->in.handle,
3778                                                          info, p->mem_ctx);
3779                         break;
3780
3781                 case SPLHND_PRINTER:
3782                         result = printer_notify_info(p, r->in.handle,
3783                                                      info, p->mem_ctx);
3784                         break;
3785         }
3786
3787         Printer->notify.fnpcn = false;
3788
3789 done:
3790         return result;
3791 }
3792
3793 /********************************************************************
3794  ********************************************************************/
3795
3796 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3797                                  const char *servername,
3798                                  const char *printername,
3799                                  const char **printername_p)
3800 {
3801         /* FIXME: add lp_force_printername() */
3802
3803         if (servername == NULL) {
3804                 *printername_p = talloc_strdup(mem_ctx, printername);
3805                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3806                 return WERR_OK;
3807         }
3808
3809         if (servername[0] == '\\' && servername[1] == '\\') {
3810                 servername += 2;
3811         }
3812
3813         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3814         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3815
3816         return WERR_OK;
3817 }
3818
3819 /********************************************************************
3820  ********************************************************************/
3821
3822 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3823                                           const char *printername)
3824 {
3825         if (dm == NULL) {
3826                 return;
3827         }
3828
3829         dm->devicename = talloc_strndup(dm, printername,
3830                                         MIN(strlen(printername), 31));
3831 }
3832
3833 /********************************************************************
3834  * construct_printer_info_0
3835  * fill a printer_info_0 struct
3836  ********************************************************************/
3837
3838 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3839                                       const struct auth_serversupplied_info *session_info,
3840                                       struct messaging_context *msg_ctx,
3841                                       struct spoolss_PrinterInfo2 *info2,
3842                                       const char *servername,
3843                                       struct spoolss_PrinterInfo0 *r,
3844                                       int snum)
3845 {
3846         int count;
3847         struct printer_session_counter *session_counter;
3848         struct timeval setuptime;
3849         print_status_struct status;
3850         WERROR result;
3851
3852         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3853         if (!W_ERROR_IS_OK(result)) {
3854                 return result;
3855         }
3856
3857         if (servername) {
3858                 r->servername = talloc_strdup(mem_ctx, servername);
3859                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3860         } else {
3861                 r->servername = NULL;
3862         }
3863
3864         count = print_queue_length(msg_ctx, snum, &status);
3865
3866         /* check if we already have a counter for this printer */
3867         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3868                 if (session_counter->snum == snum)
3869                         break;
3870         }
3871
3872         /* it's the first time, add it to the list */
3873         if (session_counter == NULL) {
3874                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3875                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3876                 session_counter->snum           = snum;
3877                 session_counter->counter        = 0;
3878                 DLIST_ADD(counter_list, session_counter);
3879         }
3880
3881         /* increment it */
3882         session_counter->counter++;
3883
3884         r->cjobs                        = count;
3885         r->total_jobs                   = 0;
3886         r->total_bytes                  = 0;
3887
3888         get_startup_time(&setuptime);
3889         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3890
3891         /* JFM:
3892          * the global_counter should be stored in a TDB as it's common to all the clients
3893          * and should be zeroed on samba startup
3894          */
3895         r->global_counter               = session_counter->counter;
3896         r->total_pages                  = 0;
3897         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3898         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3899         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3900         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3901         r->spooling                     = 0;
3902         r->max_spooling                 = 0;
3903         r->session_counter              = session_counter->counter;
3904         r->num_error_out_of_paper       = 0x0;
3905         r->num_error_not_ready          = 0x0;          /* number of print failure */
3906         r->job_error                    = 0x0;
3907         r->number_of_processors         = 0x1;
3908         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3909         r->high_part_total_bytes        = 0x0;
3910
3911         /* ChangeID in milliseconds*/
3912         winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3913                                     info2->sharename, &r->change_id);
3914
3915         r->last_error                   = WERR_OK;
3916         r->status                       = nt_printq_status(status.status);
3917         r->enumerate_network_printers   = 0x0;
3918         r->c_setprinter                 = 0x0;
3919         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3920         r->processor_level              = 0x6;          /* 6  ???*/
3921         r->ref_ic                       = 0;
3922         r->reserved2                    = 0;
3923         r->reserved3                    = 0;
3924
3925         return WERR_OK;
3926 }
3927
3928
3929 /********************************************************************
3930  * construct_printer_info1
3931  * fill a spoolss_PrinterInfo1 struct
3932 ********************************************************************/
3933
3934 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3935                                       const struct spoolss_PrinterInfo2 *info2,
3936                                       uint32_t flags,
3937                                       const char *servername,
3938                                       struct spoolss_PrinterInfo1 *r,
3939                                       int snum)
3940 {
3941         WERROR result;
3942
3943         r->flags                = flags;
3944
3945         if (info2->comment == NULL || info2->comment[0] == '\0') {
3946                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3947         } else {
3948                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3949         }
3950         W_ERROR_HAVE_NO_MEMORY(r->comment);
3951
3952         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3953         if (!W_ERROR_IS_OK(result)) {
3954                 return result;
3955         }
3956
3957         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3958                                                   r->name,
3959                                                   info2->drivername,
3960                                                   r->comment);
3961         W_ERROR_HAVE_NO_MEMORY(r->description);
3962
3963         return WERR_OK;
3964 }
3965
3966 /********************************************************************
3967  * construct_printer_info2
3968  * fill a spoolss_PrinterInfo2 struct
3969 ********************************************************************/
3970
3971 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3972                                       struct messaging_context *msg_ctx,
3973                                       const struct spoolss_PrinterInfo2 *info2,
3974                                       const char *servername,
3975                                       struct spoolss_PrinterInfo2 *r,
3976                                       int snum)
3977 {
3978         int count;
3979         print_status_struct status;
3980         WERROR result;
3981
3982         count = print_queue_length(msg_ctx, snum, &status);
3983
3984         if (servername) {
3985                 r->servername           = talloc_strdup(mem_ctx, servername);
3986                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3987         } else {
3988                 r->servername           = NULL;
3989         }
3990
3991         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3992         if (!W_ERROR_IS_OK(result)) {
3993                 return result;
3994         }
3995
3996         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3997         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3998         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3999         W_ERROR_HAVE_NO_MEMORY(r->portname);
4000         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4001         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4002
4003         if (info2->comment[0] == '\0') {
4004                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4005         } else {
4006                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4007         }
4008         W_ERROR_HAVE_NO_MEMORY(r->comment);
4009
4010         r->location             = talloc_strdup(mem_ctx, info2->location);
4011         W_ERROR_HAVE_NO_MEMORY(r->location);
4012         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4013         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4014         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4015         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4016         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4017         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4018         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4019         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4020
4021         r->attributes           = info2->attributes;
4022
4023         r->priority             = info2->priority;
4024         r->defaultpriority      = info2->defaultpriority;
4025         r->starttime            = info2->starttime;
4026         r->untiltime            = info2->untiltime;
4027         r->status               = nt_printq_status(status.status);
4028         r->cjobs                = count;
4029         r->averageppm           = info2->averageppm;
4030
4031         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4032         if (!r->devmode) {
4033                 DEBUG(8,("Returning NULL Devicemode!\n"));
4034         }
4035
4036         compose_devicemode_devicename(r->devmode, r->printername);
4037
4038         r->secdesc = NULL;
4039
4040         if (info2->secdesc != NULL) {
4041                 /* don't use talloc_steal() here unless you do a deep steal of all
4042                    the SEC_DESC members */
4043
4044                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4045         }
4046
4047         return WERR_OK;
4048 }
4049
4050 /********************************************************************
4051  * construct_printer_info3
4052  * fill a spoolss_PrinterInfo3 struct
4053  ********************************************************************/
4054
4055 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4056                                       const struct spoolss_PrinterInfo2 *info2,
4057                                       const char *servername,
4058                                       struct spoolss_PrinterInfo3 *r,
4059                                       int snum)
4060 {
4061         /* These are the components of the SD we are returning. */
4062
4063         if (info2->secdesc != NULL) {
4064                 /* don't use talloc_steal() here unless you do a deep steal of all
4065                    the SEC_DESC members */
4066
4067                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4068                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4069         }
4070
4071         return WERR_OK;
4072 }
4073
4074 /********************************************************************
4075  * construct_printer_info4
4076  * fill a spoolss_PrinterInfo4 struct
4077  ********************************************************************/
4078
4079 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4080                                       const struct spoolss_PrinterInfo2 *info2,
4081                                       const char *servername,
4082                                       struct spoolss_PrinterInfo4 *r,
4083                                       int snum)
4084 {
4085         WERROR result;
4086
4087         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4088         if (!W_ERROR_IS_OK(result)) {
4089                 return result;
4090         }
4091
4092         if (servername) {
4093                 r->servername   = talloc_strdup(mem_ctx, servername);
4094                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4095         } else {
4096                 r->servername = NULL;
4097         }
4098
4099         r->attributes   = info2->attributes;
4100
4101         return WERR_OK;
4102 }
4103
4104 /********************************************************************
4105  * construct_printer_info5
4106  * fill a spoolss_PrinterInfo5 struct
4107  ********************************************************************/
4108
4109 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4110                                       const struct spoolss_PrinterInfo2 *info2,
4111                                       const char *servername,
4112                                       struct spoolss_PrinterInfo5 *r,
4113                                       int snum)
4114 {
4115         WERROR result;
4116
4117         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4118         if (!W_ERROR_IS_OK(result)) {
4119                 return result;
4120         }
4121
4122         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4123         W_ERROR_HAVE_NO_MEMORY(r->portname);
4124
4125         r->attributes   = info2->attributes;
4126
4127         /* these two are not used by NT+ according to MSDN */
4128         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4129         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4130
4131         return WERR_OK;
4132 }
4133
4134 /********************************************************************
4135  * construct_printer_info_6
4136  * fill a spoolss_PrinterInfo6 struct
4137  ********************************************************************/
4138
4139 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4140                                       struct messaging_context *msg_ctx,
4141                                       const struct spoolss_PrinterInfo2 *info2,
4142                                       const char *servername,
4143                                       struct spoolss_PrinterInfo6 *r,
4144                                       int snum)
4145 {
4146         int count;
4147         print_status_struct status;
4148
4149         count = print_queue_length(msg_ctx, snum, &status);
4150
4151         r->status = nt_printq_status(status.status);
4152
4153         return WERR_OK;
4154 }
4155
4156 /********************************************************************
4157  * construct_printer_info7
4158  * fill a spoolss_PrinterInfo7 struct
4159  ********************************************************************/
4160
4161 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4162                                       struct messaging_context *msg_ctx,
4163                                       const char *servername,
4164                                       struct spoolss_PrinterInfo7 *r,
4165                                       int snum)
4166 {
4167         struct auth_serversupplied_info *session_info;
4168         struct GUID guid;
4169         NTSTATUS status;
4170
4171         status = make_session_info_system(mem_ctx, &session_info);
4172         if (!NT_STATUS_IS_OK(status)) {
4173                 DEBUG(0, ("construct_printer_info7: "
4174                           "Could not create system session_info\n"));
4175                 return WERR_NOMEM;
4176         }
4177
4178         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4179                                  servername,
4180                                  lp_servicename(snum), &guid, NULL)) {
4181                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4182                 r->action = DSPRINT_PUBLISH;
4183         } else {
4184                 r->guid = talloc_strdup(mem_ctx, "");
4185                 r->action = DSPRINT_UNPUBLISH;
4186         }
4187         W_ERROR_HAVE_NO_MEMORY(r->guid);
4188
4189         TALLOC_FREE(session_info);
4190         return WERR_OK;
4191 }
4192
4193 /********************************************************************
4194  * construct_printer_info8
4195  * fill a spoolss_PrinterInfo8 struct
4196  ********************************************************************/
4197
4198 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4199                                       const struct spoolss_PrinterInfo2 *info2,
4200                                       const char *servername,
4201                                       struct spoolss_DeviceModeInfo *r,
4202                                       int snum)
4203 {
4204         WERROR result;
4205         const char *printername;
4206
4207         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4208         if (!W_ERROR_IS_OK(result)) {
4209                 return result;
4210         }
4211
4212         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4213         if (!r->devmode) {
4214                 DEBUG(8,("Returning NULL Devicemode!\n"));
4215         }
4216
4217         compose_devicemode_devicename(r->devmode, printername);
4218
4219         return WERR_OK;
4220 }
4221
4222
4223 /********************************************************************
4224 ********************************************************************/
4225
4226 static bool snum_is_shared_printer(int snum)
4227 {
4228         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4229 }
4230
4231 /********************************************************************
4232  Spoolss_enumprinters.
4233 ********************************************************************/
4234
4235 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4236                                            const struct auth_serversupplied_info *session_info,
4237                                            struct messaging_context *msg_ctx,
4238                                            const char *servername,
4239                                            uint32_t level,
4240                                            uint32_t flags,
4241                                            union spoolss_PrinterInfo **info_p,
4242                                            uint32_t *count_p)
4243 {
4244         int snum;
4245         int n_services = lp_numservices();
4246         union spoolss_PrinterInfo *info = NULL;
4247         uint32_t count = 0;
4248         WERROR result = WERR_OK;
4249
4250         *count_p = 0;
4251         *info_p = NULL;
4252
4253         for (snum = 0; snum < n_services; snum++) {
4254
4255                 const char *printer;
4256                 struct spoolss_PrinterInfo2 *info2;
4257
4258                 if (!snum_is_shared_printer(snum)) {
4259                         continue;
4260                 }
4261
4262                 printer = lp_const_servicename(snum);
4263
4264                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4265                         printer, snum));
4266
4267                 result = winreg_create_printer(mem_ctx,
4268                                                session_info,
4269                                                msg_ctx,
4270                                                printer);
4271                 if (!W_ERROR_IS_OK(result)) {
4272                         goto out;
4273                 }
4274
4275                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4276                                             union spoolss_PrinterInfo,
4277                                             count + 1);
4278                 if (!info) {
4279                         result = WERR_NOMEM;
4280                         goto out;
4281                 }
4282
4283                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4284                                             printer, &info2);
4285                 if (!W_ERROR_IS_OK(result)) {
4286                         goto out;
4287                 }
4288
4289                 switch (level) {
4290                 case 0:
4291                         result = construct_printer_info0(info, session_info,
4292                                                          msg_ctx, info2,
4293                                                          servername,
4294                                                          &info[count].info0, snum);
4295                         break;
4296                 case 1:
4297                         result = construct_printer_info1(info, info2, flags,
4298                                                          servername,
4299                                                          &info[count].info1, snum);
4300                         break;
4301                 case 2:
4302                         result = construct_printer_info2(info, msg_ctx, info2,
4303                                                          servername,
4304                                                          &info[count].info2, snum);
4305                         break;
4306                 case 4:
4307                         result = construct_printer_info4(info, info2,
4308                                                          servername,
4309                                                          &info[count].info4, snum);
4310                         break;
4311                 case 5:
4312                         result = construct_printer_info5(info, info2,
4313                                                          servername,
4314                                                          &info[count].info5, snum);
4315                         break;
4316
4317                 default:
4318                         result = WERR_UNKNOWN_LEVEL;
4319                         goto out;
4320                 }
4321
4322                 if (!W_ERROR_IS_OK(result)) {
4323                         goto out;
4324                 }
4325
4326                 count++;
4327         }
4328
4329         *count_p = count;
4330         *info_p = info;
4331
4332  out:
4333         if (!W_ERROR_IS_OK(result)) {
4334                 TALLOC_FREE(info);
4335                 return result;
4336         }
4337
4338         *info_p = info;
4339
4340         return WERR_OK;
4341 }
4342
4343 /********************************************************************
4344  * handle enumeration of printers at level 0
4345  ********************************************************************/
4346
4347 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4348                                   const struct auth_serversupplied_info *session_info,
4349                                   struct messaging_context *msg_ctx,
4350                                   uint32_t flags,
4351                                   const char *servername,
4352                                   union spoolss_PrinterInfo **info,
4353                                   uint32_t *count)
4354 {
4355         DEBUG(4,("enum_all_printers_info_0\n"));
4356
4357         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4358                                             servername, 0, flags, info, count);
4359 }
4360
4361
4362 /********************************************************************
4363 ********************************************************************/
4364
4365 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4366                                        const struct auth_serversupplied_info *session_info,
4367                                        struct messaging_context *msg_ctx,
4368                                        const char *servername,
4369                                        uint32_t flags,
4370                                        union spoolss_PrinterInfo **info,
4371                                        uint32_t *count)
4372 {
4373         DEBUG(4,("enum_all_printers_info_1\n"));
4374
4375         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4376                                             servername, 1, flags, info, count);
4377 }
4378
4379 /********************************************************************
4380  enum_all_printers_info_1_local.
4381 *********************************************************************/
4382
4383 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4384                                              const struct auth_serversupplied_info *session_info,
4385                                              struct messaging_context *msg_ctx,
4386                                              const char *servername,
4387                                              union spoolss_PrinterInfo **info,
4388                                              uint32_t *count)
4389 {
4390         DEBUG(4,("enum_all_printers_info_1_local\n"));
4391
4392         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4393                                         servername, PRINTER_ENUM_ICON8, info, count);
4394 }
4395
4396 /********************************************************************
4397  enum_all_printers_info_1_name.
4398 *********************************************************************/
4399
4400 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4401                                             const struct auth_serversupplied_info *session_info,
4402                                             struct messaging_context *msg_ctx,
4403                                             const char *servername,
4404                                             union spoolss_PrinterInfo **info,
4405                                             uint32_t *count)
4406 {
4407         const char *s = servername;
4408
4409         DEBUG(4,("enum_all_printers_info_1_name\n"));
4410
4411         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4412                 s = servername + 2;
4413         }
4414
4415         if (!is_myname_or_ipaddr(s)) {
4416                 return WERR_INVALID_NAME;
4417         }
4418
4419         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4420                                         servername, PRINTER_ENUM_ICON8, info, count);
4421 }
4422
4423 /********************************************************************
4424  enum_all_printers_info_1_network.
4425 *********************************************************************/
4426
4427 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4428                                                const struct auth_serversupplied_info *session_info,
4429                                                struct messaging_context *msg_ctx,
4430                                                const char *servername,
4431                                                union spoolss_PrinterInfo **info,
4432                                                uint32_t *count)
4433 {
4434         const char *s = servername;
4435
4436         DEBUG(4,("enum_all_printers_info_1_network\n"));
4437
4438         /* If we respond to a enum_printers level 1 on our name with flags
4439            set to PRINTER_ENUM_REMOTE with a list of printers then these
4440            printers incorrectly appear in the APW browse list.
4441            Specifically the printers for the server appear at the workgroup
4442            level where all the other servers in the domain are
4443            listed. Windows responds to this call with a
4444            WERR_CAN_NOT_COMPLETE so we should do the same. */
4445
4446         if (servername[0] == '\\' && servername[1] == '\\') {
4447                  s = servername + 2;
4448         }
4449
4450         if (is_myname_or_ipaddr(s)) {
4451                  return WERR_CAN_NOT_COMPLETE;
4452         }
4453
4454         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4455                                         servername, PRINTER_ENUM_NAME, info, count);
4456 }
4457
4458 /********************************************************************
4459  * api_spoolss_enumprinters
4460  *
4461  * called from api_spoolss_enumprinters (see this to understand)
4462  ********************************************************************/
4463
4464 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4465                                        const struct auth_serversupplied_info *session_info,
4466                                        struct messaging_context *msg_ctx,
4467                                        const char *servername,
4468                                        union spoolss_PrinterInfo **info,
4469                                        uint32_t *count)
4470 {
4471         DEBUG(4,("enum_all_printers_info_2\n"));
4472
4473         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4474                                             servername, 2, 0, info, count);
4475 }
4476
4477 /********************************************************************
4478  * handle enumeration of printers at level 1
4479  ********************************************************************/
4480
4481 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4482                                   const struct auth_serversupplied_info *session_info,
4483                                   struct messaging_context *msg_ctx,
4484                                   uint32_t flags,
4485                                   const char *servername,
4486                                   union spoolss_PrinterInfo **info,
4487                                   uint32_t *count)
4488 {
4489         /* Not all the flags are equals */
4490
4491         if (flags & PRINTER_ENUM_LOCAL) {
4492                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4493                                                       msg_ctx, servername, info, count);
4494         }
4495
4496         if (flags & PRINTER_ENUM_NAME) {
4497                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4498                                                      msg_ctx, servername, info,
4499                                                      count);
4500         }
4501
4502         if (flags & PRINTER_ENUM_NETWORK) {
4503                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4504                                                         msg_ctx, servername, info,
4505                                                         count);
4506         }
4507
4508         return WERR_OK; /* NT4sp5 does that */
4509 }
4510
4511 /********************************************************************
4512  * handle enumeration of printers at level 2
4513  ********************************************************************/
4514
4515 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4516                                   const struct auth_serversupplied_info *session_info,
4517                                   struct messaging_context *msg_ctx,
4518                                   uint32_t flags,
4519                                   const char *servername,
4520                                   union spoolss_PrinterInfo **info,
4521                                   uint32_t *count)
4522 {
4523         if (flags & PRINTER_ENUM_LOCAL) {
4524
4525                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4526                                                 servername,
4527                                                 info, count);
4528         }
4529
4530         if (flags & PRINTER_ENUM_NAME) {
4531                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4532                         return WERR_INVALID_NAME;
4533                 }
4534
4535                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4536                                                 servername,
4537                                                 info, count);
4538         }
4539
4540         if (flags & PRINTER_ENUM_REMOTE) {
4541                 return WERR_UNKNOWN_LEVEL;
4542         }
4543
4544         return WERR_OK;
4545 }
4546
4547 /********************************************************************
4548  * handle enumeration of printers at level 4
4549  ********************************************************************/
4550
4551 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4552                                   const struct auth_serversupplied_info *session_info,
4553                                   struct messaging_context *msg_ctx,
4554                                   uint32_t flags,
4555                                   const char *servername,
4556                                   union spoolss_PrinterInfo **info,
4557                                   uint32_t *count)
4558 {
4559         DEBUG(4,("enum_all_printers_info_4\n"));
4560
4561         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4562                                             servername, 4, flags, info, count);
4563 }
4564
4565
4566 /********************************************************************
4567  * handle enumeration of printers at level 5
4568  ********************************************************************/
4569
4570 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4571                                   const struct auth_serversupplied_info *session_info,
4572                                   struct messaging_context *msg_ctx,
4573                                   uint32_t flags,
4574                                   const char *servername,
4575                                   union spoolss_PrinterInfo **info,
4576                                   uint32_t *count)
4577 {
4578         DEBUG(4,("enum_all_printers_info_5\n"));
4579
4580         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4581                                             servername, 5, flags, info, count);
4582 }
4583
4584 /****************************************************************
4585  _spoolss_EnumPrinters
4586 ****************************************************************/
4587
4588 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4589                              struct spoolss_EnumPrinters *r)
4590 {
4591         const struct auth_serversupplied_info *session_info = get_session_info_system();
4592         WERROR result;
4593
4594         /* that's an [in out] buffer */
4595
4596         if (!r->in.buffer && (r->in.offered != 0)) {
4597                 return WERR_INVALID_PARAM;
4598         }
4599
4600         DEBUG(4,("_spoolss_EnumPrinters\n"));
4601
4602         *r->out.needed = 0;
4603         *r->out.count = 0;
4604         *r->out.info = NULL;
4605
4606         /*
4607          * Level 1:
4608          *          flags==PRINTER_ENUM_NAME
4609          *           if name=="" then enumerates all printers
4610          *           if name!="" then enumerate the printer
4611          *          flags==PRINTER_ENUM_REMOTE
4612          *          name is NULL, enumerate printers
4613          * Level 2: name!="" enumerates printers, name can't be NULL
4614          * Level 3: doesn't exist
4615          * Level 4: does a local registry lookup
4616          * Level 5: same as Level 2
4617          */
4618
4619         if (r->in.server && r->in.server[0] == '\0') {
4620                 r->in.server = NULL;
4621         }
4622
4623         switch (r->in.level) {
4624         case 0:
4625                 result = enumprinters_level0(p->mem_ctx, session_info,
4626                                              p->msg_ctx, r->in.flags,
4627                                              r->in.server,
4628                                              r->out.info, r->out.count);
4629                 break;
4630         case 1:
4631                 result = enumprinters_level1(p->mem_ctx, session_info,
4632                                              p->msg_ctx, r->in.flags,
4633                                              r->in.server,
4634                                              r->out.info, r->out.count);
4635                 break;
4636         case 2:
4637                 result = enumprinters_level2(p->mem_ctx, session_info,
4638                                              p->msg_ctx, r->in.flags,
4639                                              r->in.server,
4640                                              r->out.info, r->out.count);
4641                 break;
4642         case 4:
4643                 result = enumprinters_level4(p->mem_ctx, session_info,
4644                                              p->msg_ctx, r->in.flags,
4645                                              r->in.server,
4646                                              r->out.info, r->out.count);
4647                 break;
4648         case 5:
4649                 result = enumprinters_level5(p->mem_ctx, session_info,
4650                                              p->msg_ctx, r->in.flags,
4651                                              r->in.server,
4652                                              r->out.info, r->out.count);
4653                 break;
4654         default:
4655                 return WERR_UNKNOWN_LEVEL;
4656         }
4657
4658         if (!W_ERROR_IS_OK(result)) {
4659                 return result;
4660         }
4661
4662         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4663                                                      spoolss_EnumPrinters,
4664                                                      *r->out.info, r->in.level,
4665                                                      *r->out.count);
4666         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4667         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4668
4669         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4670 }
4671
4672 /****************************************************************
4673  _spoolss_GetPrinter
4674 ****************************************************************/
4675
4676 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4677                            struct spoolss_GetPrinter *r)
4678 {
4679         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4680         struct spoolss_PrinterInfo2 *info2 = NULL;
4681         WERROR result = WERR_OK;
4682         int snum;
4683
4684         /* that's an [in out] buffer */
4685
4686         if (!r->in.buffer && (r->in.offered != 0)) {
4687                 return WERR_INVALID_PARAM;
4688         }
4689
4690         *r->out.needed = 0;
4691
4692         if (Printer == NULL) {
4693                 return WERR_BADFID;
4694         }
4695
4696         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4697                 return WERR_BADFID;
4698         }
4699
4700         result = winreg_get_printer(p->mem_ctx,
4701                                     get_session_info_system(),
4702                                     p->msg_ctx,
4703                                     lp_const_servicename(snum),
4704                                     &info2);
4705         if (!W_ERROR_IS_OK(result)) {
4706                 goto out;
4707         }
4708
4709         switch (r->in.level) {
4710         case 0:
4711                 result = construct_printer_info0(p->mem_ctx,
4712                                                  get_session_info_system(),
4713                                                  p->msg_ctx,
4714                                                  info2,
4715                                                  Printer->servername,
4716                                                  &r->out.info->info0,
4717                                                  snum);
4718                 break;
4719         case 1:
4720                 result = construct_printer_info1(p->mem_ctx, info2,
4721                                                  PRINTER_ENUM_ICON8,
4722                                                  Printer->servername,
4723                                                  &r->out.info->info1, snum);
4724                 break;
4725         case 2:
4726                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4727                                                  Printer->servername,
4728                                                  &r->out.info->info2, snum);
4729                 break;
4730         case 3:
4731                 result = construct_printer_info3(p->mem_ctx, info2,
4732                                                  Printer->servername,
4733                                                  &r->out.info->info3, snum);
4734                 break;
4735         case 4:
4736                 result = construct_printer_info4(p->mem_ctx, info2,
4737                                                  Printer->servername,
4738                                                  &r->out.info->info4, snum);
4739                 break;
4740         case 5:
4741                 result = construct_printer_info5(p->mem_ctx, info2,
4742                                                  Printer->servername,
4743                                                  &r->out.info->info5, snum);
4744                 break;
4745         case 6:
4746                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4747                                                  Printer->servername,
4748                                                  &r->out.info->info6, snum);
4749                 break;
4750         case 7:
4751                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4752                                                  Printer->servername,
4753                                                  &r->out.info->info7, snum);
4754                 break;
4755         case 8:
4756                 result = construct_printer_info8(p->mem_ctx, info2,
4757                                                  Printer->servername,
4758                                                  &r->out.info->info8, snum);
4759                 break;
4760         default:
4761                 result = WERR_UNKNOWN_LEVEL;
4762                 break;
4763         }
4764
4765  out:
4766         if (!W_ERROR_IS_OK(result)) {
4767                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4768                           r->in.level, win_errstr(result)));
4769                 TALLOC_FREE(r->out.info);
4770                 return result;
4771         }
4772
4773         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4774                                                r->out.info, r->in.level);
4775         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4776
4777         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4778 }
4779
4780 /********************************************************************
4781  ********************************************************************/
4782
4783 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4784         do { \
4785                 if (in && strlen(in)) { \
4786                         out = talloc_strdup(mem_ctx, in); \
4787                 } else { \
4788                         out = talloc_strdup(mem_ctx, ""); \
4789                 } \
4790                 W_ERROR_HAVE_NO_MEMORY(out); \
4791         } while (0);
4792
4793 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4794         do { \
4795                 if (in && strlen(in)) { \
4796                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4797                 } else { \
4798                         out = talloc_strdup(mem_ctx, ""); \
4799                 } \
4800                 W_ERROR_HAVE_NO_MEMORY(out); \
4801         } while (0);
4802
4803 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4804                                                   const char **string_array,
4805                                                   const char ***presult,
4806                                                   const char *cservername,
4807                                                   const char *arch,
4808                                                   int version)
4809 {
4810         int i, num_strings = 0;
4811         const char **array = NULL;
4812
4813         if (string_array == NULL) {
4814                 return WERR_INVALID_PARAMETER;
4815         }
4816
4817         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4818                 const char *str = NULL;
4819
4820                 if (cservername == NULL || arch == NULL) {
4821                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4822                 } else {
4823                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4824                 }
4825
4826                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4827                         TALLOC_FREE(array);
4828                         return WERR_NOMEM;
4829                 }
4830         }
4831
4832         if (i > 0) {
4833                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4834                              &array, &num_strings);
4835         }
4836
4837         if (presult) {
4838                 *presult = array;
4839         }
4840
4841         return WERR_OK;
4842 }
4843
4844 /********************************************************************
4845  * fill a spoolss_DriverInfo1 struct
4846  ********************************************************************/
4847
4848 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4849                                         struct spoolss_DriverInfo1 *r,
4850                                         const struct spoolss_DriverInfo8 *driver,
4851                                         const char *servername)
4852 {
4853         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4854         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4855
4856         return WERR_OK;
4857 }
4858
4859 /********************************************************************
4860  * fill a spoolss_DriverInfo2 struct
4861  ********************************************************************/
4862
4863 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4864                                         struct spoolss_DriverInfo2 *r,
4865                                         const struct spoolss_DriverInfo8 *driver,
4866                                         const char *servername)
4867
4868 {
4869         const char *cservername = canon_servername(servername);
4870
4871         r->version              = driver->version;
4872
4873         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4874         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4875         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4876         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4877
4878         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4879                                driver->architecture,
4880                                driver->version,
4881                                driver->driver_path,
4882                                r->driver_path);
4883
4884         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4885                                driver->architecture,
4886                                driver->version,
4887                                driver->data_file,
4888                                r->data_file);
4889
4890         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4891                                driver->architecture,
4892                                driver->version,
4893                                driver->config_file,
4894                                r->config_file);
4895
4896         return WERR_OK;
4897 }
4898
4899 /********************************************************************
4900  * fill a spoolss_DriverInfo3 struct
4901  ********************************************************************/
4902
4903 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4904                                         struct spoolss_DriverInfo3 *r,
4905                                         const struct spoolss_DriverInfo8 *driver,
4906                                         const char *servername)
4907 {
4908         const char *cservername = canon_servername(servername);
4909
4910         r->version              = driver->version;
4911
4912         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4913         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4914         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4915         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4916
4917         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4918                                driver->architecture,
4919                                driver->version,
4920                                driver->driver_path,
4921                                r->driver_path);
4922
4923         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4924                                driver->architecture,
4925                                driver->version,
4926                                driver->data_file,
4927                                r->data_file);
4928
4929         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4930                                driver->architecture,
4931                                driver->version,
4932                                driver->config_file,
4933                                r->config_file);
4934
4935         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4936                                driver->architecture,
4937                                driver->version,
4938                                driver->help_file,
4939                                r->help_file);
4940
4941         FILL_DRIVER_STRING(mem_ctx,
4942                            driver->monitor_name,
4943                            r->monitor_name);
4944
4945         FILL_DRIVER_STRING(mem_ctx,
4946                            driver->default_datatype,
4947                            r->default_datatype);
4948
4949         return string_array_from_driver_info(mem_ctx,
4950                                              driver->dependent_files,
4951                                              &r->dependent_files,
4952                                              cservername,
4953                                              driver->architecture,
4954                                              driver->version);
4955 }
4956
4957 /********************************************************************
4958  * fill a spoolss_DriverInfo4 struct
4959  ********************************************************************/
4960
4961 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4962                                         struct spoolss_DriverInfo4 *r,
4963                                         const struct spoolss_DriverInfo8 *driver,
4964                                         const char *servername)
4965 {
4966         const char *cservername = canon_servername(servername);
4967         WERROR result;
4968
4969         r->version              = driver->version;
4970
4971         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4972         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4973         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4974         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4975
4976         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4977                                driver->architecture,
4978                                driver->version,
4979                                driver->driver_path,
4980                                r->driver_path);
4981
4982         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4983                                driver->architecture,
4984                                driver->version,
4985                                driver->data_file,
4986                                r->data_file);
4987
4988         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4989                                driver->architecture,
4990                                driver->version,
4991                                driver->config_file,
4992                                r->config_file);
4993
4994         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4995                                driver->architecture,
4996                                driver->version,
4997                                driver->help_file,
4998                                r->help_file);
4999
5000         result = string_array_from_driver_info(mem_ctx,
5001                                                driver->dependent_files,
5002                                                &r->dependent_files,
5003                                                cservername,
5004                                                driver->architecture,
5005                                                driver->version);
5006         if (!W_ERROR_IS_OK(result)) {
5007                 return result;
5008         }
5009
5010         FILL_DRIVER_STRING(mem_ctx,
5011                            driver->monitor_name,
5012                            r->monitor_name);
5013
5014         FILL_DRIVER_STRING(mem_ctx,
5015                            driver->default_datatype,
5016                            r->default_datatype);
5017
5018
5019         result = string_array_from_driver_info(mem_ctx,
5020                                                driver->previous_names,
5021                                                &r->previous_names,
5022                                                NULL, NULL, 0);
5023
5024         return result;
5025 }
5026
5027 /********************************************************************
5028  * fill a spoolss_DriverInfo5 struct
5029  ********************************************************************/
5030
5031 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5032                                         struct spoolss_DriverInfo5 *r,
5033                                         const struct spoolss_DriverInfo8 *driver,
5034                                         const char *servername)
5035 {
5036         const char *cservername = canon_servername(servername);
5037
5038         r->version              = driver->version;
5039
5040         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5041         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5042         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5043         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5044
5045         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5046                                driver->architecture,
5047                                driver->version,
5048                                driver->driver_path,
5049                                r->driver_path);
5050
5051         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5052                                driver->architecture,
5053                                driver->version,
5054                                driver->data_file,
5055                                r->data_file);
5056
5057         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5058                                driver->architecture,
5059                                driver->version,
5060                                driver->config_file,
5061                                r->config_file);
5062
5063         r->driver_attributes    = 0;
5064         r->config_version       = 0;
5065         r->driver_version       = 0;
5066
5067         return WERR_OK;
5068 }
5069 /********************************************************************
5070  * fill a spoolss_DriverInfo6 struct
5071  ********************************************************************/
5072
5073 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5074                                         struct spoolss_DriverInfo6 *r,
5075                                         const struct spoolss_DriverInfo8 *driver,
5076                                         const char *servername)
5077 {
5078         const char *cservername = canon_servername(servername);
5079         WERROR result;
5080
5081         r->version              = driver->version;
5082
5083         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5084         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5085         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5086         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5087
5088         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5089                                driver->architecture,
5090                                driver->version,
5091                                driver->driver_path,
5092                                r->driver_path);
5093
5094         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5095                                driver->architecture,
5096                                driver->version,
5097                                driver->data_file,
5098                                r->data_file);
5099
5100         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5101                                driver->architecture,
5102                                driver->version,
5103                                driver->config_file,
5104                                r->config_file);
5105
5106         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5107                                driver->architecture,
5108                                driver->version,
5109                                driver->help_file,
5110                                r->help_file);
5111
5112         FILL_DRIVER_STRING(mem_ctx,
5113                            driver->monitor_name,
5114                            r->monitor_name);
5115
5116         FILL_DRIVER_STRING(mem_ctx,
5117                            driver->default_datatype,
5118                            r->default_datatype);
5119
5120         result = string_array_from_driver_info(mem_ctx,
5121                                                driver->dependent_files,
5122                                                &r->dependent_files,
5123                                                cservername,
5124                                                driver->architecture,
5125                                                driver->version);
5126         if (!W_ERROR_IS_OK(result)) {
5127                 return result;
5128         }
5129
5130         result = string_array_from_driver_info(mem_ctx,
5131                                                driver->previous_names,
5132                                                &r->previous_names,
5133                                                NULL, NULL, 0);
5134         if (!W_ERROR_IS_OK(result)) {
5135                 return result;
5136         }
5137
5138         r->driver_date          = driver->driver_date;
5139         r->driver_version       = driver->driver_version;
5140
5141         FILL_DRIVER_STRING(mem_ctx,
5142                            driver->manufacturer_name,
5143                            r->manufacturer_name);
5144         FILL_DRIVER_STRING(mem_ctx,
5145                            driver->manufacturer_url,
5146                            r->manufacturer_url);
5147         FILL_DRIVER_STRING(mem_ctx,
5148                            driver->hardware_id,
5149                            r->hardware_id);
5150         FILL_DRIVER_STRING(mem_ctx,
5151                            driver->provider,
5152                            r->provider);
5153
5154         return WERR_OK;
5155 }
5156
5157 /********************************************************************
5158  * fill a spoolss_DriverInfo8 struct
5159  ********************************************************************/
5160
5161 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5162                                         struct spoolss_DriverInfo8 *r,
5163                                         const struct spoolss_DriverInfo8 *driver,
5164                                         const char *servername)
5165 {
5166         const char *cservername = canon_servername(servername);
5167         WERROR result;
5168
5169         r->version              = driver->version;
5170
5171         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5172         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5173         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5174         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5175
5176         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5177                                driver->architecture,
5178                                driver->version,
5179                                driver->driver_path,
5180                                r->driver_path);
5181
5182         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5183                                driver->architecture,
5184                                driver->version,
5185                                driver->data_file,
5186                                r->data_file);
5187
5188         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5189                                driver->architecture,
5190                                driver->version,
5191                                driver->config_file,
5192                                r->config_file);
5193
5194         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5195                                driver->architecture,
5196                                driver->version,
5197                                driver->help_file,
5198                                r->help_file);
5199
5200         FILL_DRIVER_STRING(mem_ctx,
5201                            driver->monitor_name,
5202                            r->monitor_name);
5203
5204         FILL_DRIVER_STRING(mem_ctx,
5205                            driver->default_datatype,
5206                            r->default_datatype);
5207
5208         result = string_array_from_driver_info(mem_ctx,
5209                                                driver->dependent_files,
5210                                                &r->dependent_files,
5211                                                cservername,
5212                                                driver->architecture,
5213                                                driver->version);
5214         if (!W_ERROR_IS_OK(result)) {
5215                 return result;
5216         }
5217
5218         result = string_array_from_driver_info(mem_ctx,
5219                                                driver->previous_names,
5220                                                &r->previous_names,
5221                                                NULL, NULL, 0);
5222         if (!W_ERROR_IS_OK(result)) {
5223                 return result;
5224         }
5225
5226         r->driver_date          = driver->driver_date;
5227         r->driver_version       = driver->driver_version;
5228
5229         FILL_DRIVER_STRING(mem_ctx,
5230                            driver->manufacturer_name,
5231                            r->manufacturer_name);
5232         FILL_DRIVER_STRING(mem_ctx,
5233                            driver->manufacturer_url,
5234                            r->manufacturer_url);
5235         FILL_DRIVER_STRING(mem_ctx,
5236                            driver->hardware_id,
5237                            r->hardware_id);
5238         FILL_DRIVER_STRING(mem_ctx,
5239                            driver->provider,
5240                            r->provider);
5241
5242         FILL_DRIVER_STRING(mem_ctx,
5243                            driver->print_processor,
5244                            r->print_processor);
5245         FILL_DRIVER_STRING(mem_ctx,
5246                            driver->vendor_setup,
5247                            r->vendor_setup);
5248
5249         result = string_array_from_driver_info(mem_ctx,
5250                                                driver->color_profiles,
5251                                                &r->color_profiles,
5252                                                NULL, NULL, 0);
5253         if (!W_ERROR_IS_OK(result)) {
5254                 return result;
5255         }
5256
5257         FILL_DRIVER_STRING(mem_ctx,
5258                            driver->inf_path,
5259                            r->inf_path);
5260
5261         r->printer_driver_attributes    = driver->printer_driver_attributes;
5262
5263         result = string_array_from_driver_info(mem_ctx,
5264                                                driver->core_driver_dependencies,
5265                                                &r->core_driver_dependencies,
5266                                                NULL, NULL, 0);
5267         if (!W_ERROR_IS_OK(result)) {
5268                 return result;
5269         }
5270
5271         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5272         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5273
5274         return WERR_OK;
5275 }
5276
5277 #if 0 /* disabled until marshalling issues are resolved - gd */
5278 /********************************************************************
5279  ********************************************************************/
5280
5281 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5282                                           struct spoolss_DriverFileInfo *r,
5283                                           const char *cservername,
5284                                           const char *file_name,
5285                                           enum spoolss_DriverFileType file_type,
5286                                           uint32_t file_version)
5287 {
5288         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5289                                           cservername, file_name);
5290         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5291         r->file_type    = file_type;
5292         r->file_version = file_version;
5293
5294         return WERR_OK;
5295 }
5296
5297 /********************************************************************
5298  ********************************************************************/
5299
5300 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5301                                                  const struct spoolss_DriverInfo8 *driver,
5302                                                  const char *cservername,
5303                                                  struct spoolss_DriverFileInfo **info_p,
5304                                                  uint32_t *count_p)
5305 {
5306         struct spoolss_DriverFileInfo *info = NULL;
5307         uint32_t count = 0;
5308         WERROR result;
5309         uint32_t i;
5310
5311         *info_p = NULL;
5312         *count_p = 0;
5313
5314         if (strlen(driver->driver_path)) {
5315                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5316                                             struct spoolss_DriverFileInfo,
5317                                             count + 1);
5318                 W_ERROR_HAVE_NO_MEMORY(info);
5319                 result = fill_spoolss_DriverFileInfo(info,
5320                                                      &info[count],
5321                                                      cservername,
5322                                                      driver->driver_path,
5323                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5324                                                      0);
5325                 W_ERROR_NOT_OK_RETURN(result);
5326                 count++;
5327         }
5328
5329         if (strlen(driver->config_file)) {
5330                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5331                                             struct spoolss_DriverFileInfo,
5332                                             count + 1);
5333                 W_ERROR_HAVE_NO_MEMORY(info);
5334                 result = fill_spoolss_DriverFileInfo(info,
5335                                                      &info[count],
5336                                                      cservername,
5337                                                      driver->config_file,
5338                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5339                                                      0);
5340                 W_ERROR_NOT_OK_RETURN(result);
5341                 count++;
5342         }
5343
5344         if (strlen(driver->data_file)) {
5345                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5346                                             struct spoolss_DriverFileInfo,
5347                                             count + 1);
5348                 W_ERROR_HAVE_NO_MEMORY(info);
5349                 result = fill_spoolss_DriverFileInfo(info,
5350                                                      &info[count],
5351                                                      cservername,
5352                                                      driver->data_file,
5353                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5354                                                      0);
5355                 W_ERROR_NOT_OK_RETURN(result);
5356                 count++;
5357         }
5358
5359         if (strlen(driver->help_file)) {
5360                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5361                                             struct spoolss_DriverFileInfo,
5362                                             count + 1);
5363                 W_ERROR_HAVE_NO_MEMORY(info);
5364                 result = fill_spoolss_DriverFileInfo(info,
5365                                                      &info[count],
5366                                                      cservername,
5367                                                      driver->help_file,
5368                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5369                                                      0);
5370                 W_ERROR_NOT_OK_RETURN(result);
5371                 count++;
5372         }
5373
5374         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5375                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5376                                             struct spoolss_DriverFileInfo,
5377                                             count + 1);
5378                 W_ERROR_HAVE_NO_MEMORY(info);
5379                 result = fill_spoolss_DriverFileInfo(info,
5380                                                      &info[count],
5381                                                      cservername,
5382                                                      driver->dependent_files[i],
5383                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5384                                                      0);
5385                 W_ERROR_NOT_OK_RETURN(result);
5386                 count++;
5387         }
5388
5389         *info_p = info;
5390         *count_p = count;
5391
5392         return WERR_OK;
5393 }
5394
5395 /********************************************************************
5396  * fill a spoolss_DriverInfo101 struct
5397  ********************************************************************/
5398
5399 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5400                                           struct spoolss_DriverInfo101 *r,
5401                                           const struct spoolss_DriverInfo8 *driver,
5402                                           const char *servername)
5403 {
5404         const char *cservername = canon_servername(servername);
5405         WERROR result;
5406
5407         r->version              = driver->version;
5408
5409         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5410         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5411         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5412         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5413
5414         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5415                                                     cservername,
5416                                                     &r->file_info,
5417                                                     &r->file_count);
5418         if (!W_ERROR_IS_OK(result)) {
5419                 return result;
5420         }
5421
5422         FILL_DRIVER_STRING(mem_ctx,
5423                            driver->monitor_name,
5424                            r->monitor_name);
5425
5426         FILL_DRIVER_STRING(mem_ctx,
5427                            driver->default_datatype,
5428                            r->default_datatype);
5429
5430         result = string_array_from_driver_info(mem_ctx,
5431                                                driver->previous_names,
5432                                                &r->previous_names,
5433                                                NULL, NULL, 0);
5434         if (!W_ERROR_IS_OK(result)) {
5435                 return result;
5436         }
5437
5438         r->driver_date          = driver->driver_date;
5439         r->driver_version       = driver->driver_version;
5440
5441         FILL_DRIVER_STRING(mem_ctx,
5442                            driver->manufacturer_name,
5443                            r->manufacturer_name);
5444         FILL_DRIVER_STRING(mem_ctx,
5445                            driver->manufacturer_url,
5446                            r->manufacturer_url);
5447         FILL_DRIVER_STRING(mem_ctx,
5448                            driver->hardware_id,
5449                            r->hardware_id);
5450         FILL_DRIVER_STRING(mem_ctx,
5451                            driver->provider,
5452                            r->provider);
5453
5454         return WERR_OK;
5455 }
5456 #endif
5457 /********************************************************************
5458  ********************************************************************/
5459
5460 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5461                                                   const struct auth_serversupplied_info *session_info,
5462                                                   struct messaging_context *msg_ctx,
5463                                                   uint32_t level,
5464                                                   union spoolss_DriverInfo *r,
5465                                                   int snum,
5466                                                   const char *servername,
5467                                                   const char *architecture,
5468                                                   uint32_t version)
5469 {
5470         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5471         struct spoolss_DriverInfo8 *driver;
5472         WERROR result;
5473
5474         if (level == 101) {
5475                 return WERR_UNKNOWN_LEVEL;
5476         }
5477
5478         result = winreg_get_printer(mem_ctx,
5479                                     session_info,
5480                                     msg_ctx,
5481                                     lp_const_servicename(snum),
5482                                     &pinfo2);
5483
5484         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5485                 win_errstr(result)));
5486
5487         if (!W_ERROR_IS_OK(result)) {
5488                 return WERR_INVALID_PRINTER_NAME;
5489         }
5490
5491         result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5492                                    architecture,
5493                                    pinfo2->drivername, version, &driver);
5494
5495         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5496                 win_errstr(result)));
5497
5498         if (!W_ERROR_IS_OK(result)) {
5499                 /*
5500                  * Is this a W2k client ?
5501                  */
5502
5503                 if (version < 3) {
5504                         talloc_free(pinfo2);
5505                         return WERR_UNKNOWN_PRINTER_DRIVER;
5506                 }
5507
5508                 /* Yes - try again with a WinNT driver. */
5509                 version = 2;
5510                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5511                                            architecture,
5512                                            pinfo2->drivername,
5513                                            version, &driver);
5514                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5515                         win_errstr(result)));
5516                 if (!W_ERROR_IS_OK(result)) {
5517                         talloc_free(pinfo2);
5518                         return WERR_UNKNOWN_PRINTER_DRIVER;
5519                 }
5520         }
5521
5522         switch (level) {
5523         case 1:
5524                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5525                 break;
5526         case 2:
5527                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5528                 break;
5529         case 3:
5530                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5531                 break;
5532         case 4:
5533                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5534                 break;
5535         case 5:
5536                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5537                 break;
5538         case 6:
5539                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5540                 break;
5541         case 8:
5542                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5543                 break;
5544 #if 0 /* disabled until marshalling issues are resolved - gd */
5545         case 101:
5546                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5547                 break;
5548 #endif
5549         default:
5550                 result = WERR_UNKNOWN_LEVEL;
5551                 break;
5552         }
5553
5554         talloc_free(pinfo2);
5555         talloc_free(driver);
5556
5557         return result;
5558 }
5559
5560 /****************************************************************
5561  _spoolss_GetPrinterDriver2
5562 ****************************************************************/
5563
5564 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5565                                   struct spoolss_GetPrinterDriver2 *r)
5566 {
5567         struct printer_handle *printer;
5568         WERROR result;
5569
5570         int snum;
5571
5572         /* that's an [in out] buffer */
5573
5574         if (!r->in.buffer && (r->in.offered != 0)) {
5575                 return WERR_INVALID_PARAM;
5576         }
5577
5578         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5579
5580         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5581                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5582                 return WERR_INVALID_PRINTER_NAME;
5583         }
5584
5585         *r->out.needed = 0;
5586         *r->out.server_major_version = 0;
5587         *r->out.server_minor_version = 0;
5588
5589         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5590                 return WERR_BADFID;
5591         }
5592
5593         result = construct_printer_driver_info_level(p->mem_ctx,
5594                                                      get_session_info_system(),
5595                                                      p->msg_ctx,
5596                                                      r->in.level, r->out.info,
5597                                                      snum, printer->servername,
5598                                                      r->in.architecture,
5599                                                      r->in.client_major_version);
5600         if (!W_ERROR_IS_OK(result)) {
5601                 TALLOC_FREE(r->out.info);
5602                 return result;
5603         }
5604
5605         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5606                                                r->out.info, r->in.level);
5607         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5608
5609         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5610 }
5611
5612
5613 /****************************************************************
5614  _spoolss_StartPagePrinter
5615 ****************************************************************/
5616
5617 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5618                                  struct spoolss_StartPagePrinter *r)
5619 {
5620         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5621
5622         if (!Printer) {
5623                 DEBUG(3,("_spoolss_StartPagePrinter: "
5624                         "Error in startpageprinter printer handle\n"));
5625                 return WERR_BADFID;
5626         }
5627
5628         Printer->page_started = true;
5629         return WERR_OK;
5630 }
5631
5632 /****************************************************************
5633  _spoolss_EndPagePrinter
5634 ****************************************************************/
5635
5636 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5637                                struct spoolss_EndPagePrinter *r)
5638 {
5639         int snum;
5640
5641         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5642
5643         if (!Printer) {
5644                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5645                         OUR_HANDLE(r->in.handle)));
5646                 return WERR_BADFID;
5647         }
5648
5649         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5650                 return WERR_BADFID;
5651
5652         Printer->page_started = false;
5653         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5654
5655         return WERR_OK;
5656 }
5657
5658 /****************************************************************
5659  _spoolss_StartDocPrinter
5660 ****************************************************************/
5661
5662 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5663                                 struct spoolss_StartDocPrinter *r)
5664 {
5665         struct spoolss_DocumentInfo1 *info_1;
5666         int snum;
5667         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5668         WERROR werr;
5669
5670         if (!Printer) {
5671                 DEBUG(2,("_spoolss_StartDocPrinter: "
5672                         "Invalid handle (%s:%u:%u)\n",
5673                         OUR_HANDLE(r->in.handle)));
5674                 return WERR_BADFID;
5675         }
5676
5677         if (Printer->jobid) {
5678                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5679                           "StartDocPrinter called twice! "
5680                           "(existing jobid = %d)\n", Printer->jobid));
5681                 return WERR_INVALID_HANDLE;
5682         }
5683
5684         if (r->in.level != 1) {
5685                 return WERR_UNKNOWN_LEVEL;
5686         }
5687
5688         info_1 = r->in.info.info1;
5689
5690         /*
5691          * a nice thing with NT is it doesn't listen to what you tell it.
5692          * when asked to send _only_ RAW datas, it tries to send datas
5693          * in EMF format.
5694          *
5695          * So I add checks like in NT Server ...
5696          */
5697
5698         if (info_1->datatype) {
5699                 if (strcmp(info_1->datatype, "RAW") != 0) {
5700                         *r->out.job_id = 0;
5701                         return WERR_INVALID_DATATYPE;
5702                 }
5703         }
5704
5705         /* get the share number of the printer */
5706         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5707                 return WERR_BADFID;
5708         }
5709
5710         werr = print_job_start(p->session_info,
5711                                p->msg_ctx,
5712                                p->client_id->name,
5713                                snum,
5714                                info_1->document_name,
5715                                info_1->output_file,
5716                                Printer->devmode,
5717                                &Printer->jobid);
5718
5719         /* An error occured in print_job_start() so return an appropriate
5720            NT error code. */
5721
5722         if (!W_ERROR_IS_OK(werr)) {
5723                 return werr;
5724         }
5725
5726         Printer->document_started = true;
5727         *r->out.job_id = Printer->jobid;
5728
5729         return WERR_OK;
5730 }
5731
5732 /****************************************************************
5733  _spoolss_EndDocPrinter
5734 ****************************************************************/
5735
5736 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5737                               struct spoolss_EndDocPrinter *r)
5738 {
5739         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5740         NTSTATUS status;
5741         int snum;
5742
5743         if (!Printer) {
5744                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5745                         OUR_HANDLE(r->in.handle)));
5746                 return WERR_BADFID;
5747         }
5748
5749         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5750                 return WERR_BADFID;
5751         }
5752
5753         Printer->document_started = false;
5754         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5755         if (!NT_STATUS_IS_OK(status)) {
5756                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5757                           "print_job_end failed [%s]\n",
5758                           nt_errstr(status)));
5759         }
5760
5761         Printer->jobid = 0;
5762         return ntstatus_to_werror(status);
5763 }
5764
5765 /****************************************************************
5766  _spoolss_WritePrinter
5767 ****************************************************************/
5768
5769 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5770                              struct spoolss_WritePrinter *r)
5771 {
5772         ssize_t buffer_written;
5773         int snum;
5774         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5775
5776         if (!Printer) {
5777                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5778                         OUR_HANDLE(r->in.handle)));
5779                 *r->out.num_written = r->in._data_size;
5780                 return WERR_BADFID;
5781         }
5782
5783         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5784                 return WERR_BADFID;
5785
5786         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5787         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5788                                                    snum, Printer->jobid,
5789                                                    (const char *)r->in.data.data,
5790                                                    (size_t)r->in._data_size);
5791         if (buffer_written == (ssize_t)-1) {
5792                 *r->out.num_written = 0;
5793                 if (errno == ENOSPC)
5794                         return WERR_NO_SPOOL_SPACE;
5795                 else
5796                         return WERR_ACCESS_DENIED;
5797         }
5798
5799         *r->out.num_written = r->in._data_size;
5800
5801         return WERR_OK;
5802 }
5803
5804 /********************************************************************
5805  * api_spoolss_getprinter
5806  * called from the spoolss dispatcher
5807  *
5808  ********************************************************************/
5809
5810 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5811                               struct pipes_struct *p)
5812 {
5813         const struct auth_serversupplied_info *session_info = p->session_info;
5814         int snum;
5815         WERROR errcode = WERR_BADFUNC;
5816         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5817
5818         if (!Printer) {
5819                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5820                         OUR_HANDLE(handle)));
5821                 return WERR_BADFID;
5822         }
5823
5824         if (!get_printer_snum(p, handle, &snum, NULL))
5825                 return WERR_BADFID;
5826
5827         switch (command) {
5828         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5829                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5830                 break;
5831         case SPOOLSS_PRINTER_CONTROL_RESUME:
5832         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5833                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5834                 break;
5835         case SPOOLSS_PRINTER_CONTROL_PURGE:
5836                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5837                 break;
5838         default:
5839                 return WERR_UNKNOWN_LEVEL;
5840         }
5841
5842         return errcode;
5843 }
5844
5845
5846 /****************************************************************
5847  _spoolss_AbortPrinter
5848  * From MSDN: "Deletes printer's spool file if printer is configured
5849  * for spooling"
5850 ****************************************************************/
5851
5852 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5853                              struct spoolss_AbortPrinter *r)
5854 {
5855         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5856         int             snum;
5857         WERROR          errcode = WERR_OK;
5858
5859         if (!Printer) {
5860                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5861                         OUR_HANDLE(r->in.handle)));
5862                 return WERR_BADFID;
5863         }
5864
5865         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5866                 return WERR_BADFID;
5867
5868         if (!Printer->document_started) {
5869                 return WERR_SPL_NO_STARTDOC;
5870         }
5871
5872         errcode = print_job_delete(p->session_info,
5873                                    p->msg_ctx,
5874                                    snum,
5875                                    Printer->jobid);
5876
5877         return errcode;
5878 }
5879
5880 /********************************************************************
5881  * called by spoolss_api_setprinter
5882  * when updating a printer description
5883  ********************************************************************/
5884
5885 static WERROR update_printer_sec(struct policy_handle *handle,
5886                                  struct pipes_struct *p,
5887                                  struct sec_desc_buf *secdesc_ctr)
5888 {
5889         struct spoolss_security_descriptor *new_secdesc = NULL;
5890         struct spoolss_security_descriptor *old_secdesc = NULL;
5891         const char *printer;
5892         WERROR result;
5893         int snum;
5894
5895         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5896
5897         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5898                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5899                          OUR_HANDLE(handle)));
5900
5901                 result = WERR_BADFID;
5902                 goto done;
5903         }
5904
5905         if (secdesc_ctr == NULL) {
5906                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5907                 result = WERR_INVALID_PARAM;
5908                 goto done;
5909         }
5910         printer = lp_const_servicename(snum);
5911
5912         /* Check the user has permissions to change the security
5913            descriptor.  By experimentation with two NT machines, the user
5914            requires Full Access to the printer to change security
5915            information. */
5916
5917         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5918                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5919                 result = WERR_ACCESS_DENIED;
5920                 goto done;
5921         }
5922
5923         /* NT seems to like setting the security descriptor even though
5924            nothing may have actually changed. */
5925         result = winreg_get_printer_secdesc(p->mem_ctx,
5926                                             get_session_info_system(),
5927                                             p->msg_ctx,
5928                                             printer,
5929                                             &old_secdesc);
5930         if (!W_ERROR_IS_OK(result)) {
5931                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5932                 result = WERR_BADFID;
5933                 goto done;
5934         }
5935
5936         if (DEBUGLEVEL >= 10) {
5937                 struct security_acl *the_acl;
5938                 int i;
5939
5940                 the_acl = old_secdesc->dacl;
5941                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5942                            printer, the_acl->num_aces));
5943
5944                 for (i = 0; i < the_acl->num_aces; i++) {
5945                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5946                                            &the_acl->aces[i].trustee),
5947                                   the_acl->aces[i].access_mask));
5948                 }
5949
5950                 the_acl = secdesc_ctr->sd->dacl;
5951
5952                 if (the_acl) {
5953                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5954                                    printer, the_acl->num_aces));
5955
5956                         for (i = 0; i < the_acl->num_aces; i++) {
5957                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5958                                                    &the_acl->aces[i].trustee),
5959                                            the_acl->aces[i].access_mask));
5960                         }
5961                 } else {
5962                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5963                 }
5964         }
5965
5966         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5967         if (new_secdesc == NULL) {
5968                 result = WERR_NOMEM;
5969                 goto done;
5970         }
5971
5972         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5973                 result = WERR_OK;
5974                 goto done;
5975         }
5976
5977         result = winreg_set_printer_secdesc(p->mem_ctx,
5978                                             get_session_info_system(),
5979                                             p->msg_ctx,
5980                                             printer,
5981                                             new_secdesc);
5982
5983  done:
5984         return result;
5985 }
5986
5987 /********************************************************************
5988  Canonicalize printer info from a client
5989  ********************************************************************/
5990
5991 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5992                              struct spoolss_SetPrinterInfo2 *info2,
5993                              int snum)
5994 {
5995         fstring printername;
5996         const char *p;
5997
5998         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5999                 "portname=%s drivername=%s comment=%s location=%s\n",
6000                 info2->servername, info2->printername, info2->sharename,
6001                 info2->portname, info2->drivername, info2->comment,
6002                 info2->location));
6003
6004         /* we force some elements to "correct" values */
6005         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6006         if (info2->servername == NULL) {
6007                 return false;
6008         }
6009         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6010         if (info2->sharename == NULL) {
6011                 return false;
6012         }
6013
6014         /* check to see if we allow printername != sharename */
6015         if (lp_force_printername(snum)) {
6016                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6017                                         global_myname(), info2->sharename);
6018         } else {
6019                 /* make sure printername is in \\server\printername format */
6020                 fstrcpy(printername, info2->printername);
6021                 p = printername;
6022                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6023                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6024                                 p++;
6025                 }
6026
6027                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6028                                         global_myname(), p);
6029         }
6030         if (info2->printername == NULL) {
6031                 return false;
6032         }
6033
6034         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6035         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6036
6037         return true;
6038 }
6039
6040 /****************************************************************************
6041 ****************************************************************************/
6042
6043 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6044 {
6045         char *cmd = lp_addport_cmd();
6046         char *command = NULL;
6047         int ret;
6048         bool is_print_op = false;
6049
6050         if ( !*cmd ) {
6051                 return WERR_ACCESS_DENIED;
6052         }
6053
6054         command = talloc_asprintf(ctx,
6055                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6056         if (!command) {
6057                 return WERR_NOMEM;
6058         }
6059
6060         if ( token )
6061                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6062
6063         DEBUG(10,("Running [%s]\n", command));
6064
6065         /********* BEGIN SePrintOperatorPrivilege **********/
6066
6067         if ( is_print_op )
6068                 become_root();
6069
6070         ret = smbrun(command, NULL);
6071
6072         if ( is_print_op )
6073                 unbecome_root();
6074
6075         /********* END SePrintOperatorPrivilege **********/
6076
6077         DEBUGADD(10,("returned [%d]\n", ret));
6078
6079         TALLOC_FREE(command);
6080
6081         if ( ret != 0 ) {
6082                 return WERR_ACCESS_DENIED;
6083         }
6084
6085         return WERR_OK;
6086 }
6087
6088 /****************************************************************************
6089 ****************************************************************************/
6090
6091 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6092                              struct spoolss_SetPrinterInfo2 *info2,
6093                              const char *remote_machine,
6094                              struct messaging_context *msg_ctx)
6095 {
6096         char *cmd = lp_addprinter_cmd();
6097         char **qlines;
6098         char *command = NULL;
6099         int numlines;
6100         int ret;
6101         int fd;
6102         bool is_print_op = false;
6103
6104         if (!remote_machine) {
6105                 return false;
6106         }
6107
6108         command = talloc_asprintf(ctx,
6109                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6110                         cmd, info2->printername, info2->sharename,
6111                         info2->portname, info2->drivername,
6112                         info2->location, info2->comment, remote_machine);
6113         if (!command) {
6114                 return false;
6115         }
6116
6117         if ( token )
6118                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6119
6120         DEBUG(10,("Running [%s]\n", command));
6121
6122         /********* BEGIN SePrintOperatorPrivilege **********/
6123
6124         if ( is_print_op )
6125                 become_root();
6126
6127         if ( (ret = smbrun(command, &fd)) == 0 ) {
6128                 /* Tell everyone we updated smb.conf. */
6129                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6130         }
6131
6132         if ( is_print_op )
6133                 unbecome_root();
6134
6135         /********* END SePrintOperatorPrivilege **********/
6136
6137         DEBUGADD(10,("returned [%d]\n", ret));
6138
6139         TALLOC_FREE(command);
6140
6141         if ( ret != 0 ) {
6142                 if (fd != -1)
6143                         close(fd);
6144                 return false;
6145         }
6146
6147         /* reload our services immediately */
6148         become_root();
6149         reload_services(msg_ctx, -1, false);
6150         unbecome_root();
6151
6152         numlines = 0;
6153         /* Get lines and convert them back to dos-codepage */
6154         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6155         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6156         close(fd);
6157
6158         /* Set the portname to what the script says the portname should be. */
6159         /* but don't require anything to be return from the script exit a good error code */
6160
6161         if (numlines) {
6162                 /* Set the portname to what the script says the portname should be. */
6163                 info2->portname = talloc_strdup(ctx, qlines[0]);
6164                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6165         }
6166
6167         TALLOC_FREE(qlines);
6168         return true;
6169 }
6170
6171 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6172                                const struct auth_serversupplied_info *session_info,
6173                                struct messaging_context *msg_ctx,
6174                                int snum,
6175                                struct spoolss_SetPrinterInfo2 *printer,
6176                                struct spoolss_PrinterInfo2 *old_printer)
6177 {
6178         bool force_update = (old_printer == NULL);
6179         const char *dnsdomname;
6180         const char *longname;
6181         const char *uncname;
6182         const char *spooling;
6183         DATA_BLOB buffer;
6184         WERROR result = WERR_OK;
6185
6186         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6187                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6188                 winreg_set_printer_dataex(mem_ctx,
6189                                           session_info,
6190                                           msg_ctx,
6191                                           printer->sharename,
6192                                           SPOOL_DSSPOOLER_KEY,
6193                                           SPOOL_REG_DRIVERNAME,
6194                                           REG_SZ,
6195                                           buffer.data,
6196                                           buffer.length);
6197
6198                 if (!force_update) {
6199                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6200                                 printer->drivername));
6201
6202                         notify_printer_driver(server_event_context(), msg_ctx,
6203                                               snum, printer->drivername ?
6204                                               printer->drivername : "");
6205                 }
6206         }
6207
6208         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6209                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6210                 winreg_set_printer_dataex(mem_ctx,
6211                                           session_info,
6212                                           msg_ctx,
6213                                           printer->sharename,
6214                                           SPOOL_DSSPOOLER_KEY,
6215                                           SPOOL_REG_DESCRIPTION,
6216                                           REG_SZ,
6217                                           buffer.data,
6218                                           buffer.length);
6219
6220                 if (!force_update) {
6221                         notify_printer_comment(server_event_context(), msg_ctx,
6222                                                snum, printer->comment ?
6223                                                printer->comment : "");
6224                 }
6225         }
6226
6227         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6228                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6229                 winreg_set_printer_dataex(mem_ctx,
6230                                           session_info,
6231                                           msg_ctx,
6232                                           printer->sharename,
6233                                           SPOOL_DSSPOOLER_KEY,
6234                                           SPOOL_REG_PRINTSHARENAME,
6235                                           REG_SZ,
6236                                           buffer.data,
6237                                           buffer.length);
6238
6239                 if (!force_update) {
6240                         notify_printer_sharename(server_event_context(),
6241                                                  msg_ctx,
6242                                                  snum, printer->sharename ?
6243                                                  printer->sharename : "");
6244                 }
6245         }
6246
6247         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6248                 const char *p;
6249
6250                 p = strrchr(printer->printername, '\\' );
6251                 if (p != NULL) {
6252                         p++;
6253                 } else {
6254                         p = printer->printername;
6255                 }
6256
6257                 push_reg_sz(mem_ctx, &buffer, p);
6258                 winreg_set_printer_dataex(mem_ctx,
6259                                           session_info,
6260                                           msg_ctx,
6261                                           printer->sharename,
6262                                           SPOOL_DSSPOOLER_KEY,
6263                                           SPOOL_REG_PRINTERNAME,
6264                                           REG_SZ,
6265                                           buffer.data,
6266                                           buffer.length);
6267
6268                 if (!force_update) {
6269                         notify_printer_printername(server_event_context(),
6270                                                    msg_ctx, snum, p ? p : "");
6271                 }
6272         }
6273
6274         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6275                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6276                 winreg_set_printer_dataex(mem_ctx,
6277                                           session_info,
6278                                           msg_ctx,
6279                                           printer->sharename,
6280                                           SPOOL_DSSPOOLER_KEY,
6281                                           SPOOL_REG_PORTNAME,
6282                                           REG_SZ,
6283                                           buffer.data,
6284                                           buffer.length);
6285
6286                 if (!force_update) {
6287                         notify_printer_port(server_event_context(),
6288                                             msg_ctx, snum, printer->portname ?
6289                                             printer->portname : "");
6290                 }
6291         }
6292
6293         if (force_update || !strequal(printer->location, old_printer->location)) {
6294                 push_reg_sz(mem_ctx, &buffer, printer->location);
6295                 winreg_set_printer_dataex(mem_ctx,
6296                                           session_info,
6297                                           msg_ctx,
6298                                           printer->sharename,
6299                                           SPOOL_DSSPOOLER_KEY,
6300                                           SPOOL_REG_LOCATION,
6301                                           REG_SZ,
6302                                           buffer.data,
6303                                           buffer.length);
6304
6305                 if (!force_update) {
6306                         notify_printer_location(server_event_context(),
6307                                                 msg_ctx, snum,
6308                                                 printer->location ?
6309                                                 printer->location : "");
6310                 }
6311         }
6312
6313         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6314                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6315                 winreg_set_printer_dataex(mem_ctx,
6316                                           session_info,
6317                                           msg_ctx,
6318                                           printer->sharename,
6319                                           SPOOL_DSSPOOLER_KEY,
6320                                           SPOOL_REG_PRINTSEPARATORFILE,
6321                                           REG_SZ,
6322                                           buffer.data,
6323                                           buffer.length);
6324
6325                 if (!force_update) {
6326                         notify_printer_sepfile(server_event_context(),
6327                                                msg_ctx, snum,
6328                                                printer->sepfile ?
6329                                                printer->sepfile : "");
6330                 }
6331         }
6332
6333         if (force_update || printer->starttime != old_printer->starttime) {
6334                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6335                 SIVAL(buffer.data, 0, printer->starttime);
6336                 winreg_set_printer_dataex(mem_ctx,
6337                                           session_info,
6338                                           msg_ctx,
6339                                           printer->sharename,
6340                                           SPOOL_DSSPOOLER_KEY,
6341                                           SPOOL_REG_PRINTSTARTTIME,
6342                                           REG_DWORD,
6343                                           buffer.data,
6344                                           buffer.length);
6345         }
6346
6347         if (force_update || printer->untiltime != old_printer->untiltime) {
6348                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6349                 SIVAL(buffer.data, 0, printer->untiltime);
6350                 winreg_set_printer_dataex(mem_ctx,
6351                                           session_info,
6352                                           msg_ctx,
6353                                           printer->sharename,
6354                                           SPOOL_DSSPOOLER_KEY,
6355                                           SPOOL_REG_PRINTENDTIME,
6356                                           REG_DWORD,
6357                                           buffer.data,
6358                                           buffer.length);
6359         }
6360
6361         if (force_update || printer->priority != old_printer->priority) {
6362                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6363                 SIVAL(buffer.data, 0, printer->priority);
6364                 winreg_set_printer_dataex(mem_ctx,
6365                                           session_info,
6366                                           msg_ctx,
6367                                           printer->sharename,
6368                                           SPOOL_DSSPOOLER_KEY,
6369                                           SPOOL_REG_PRIORITY,
6370                                           REG_DWORD,
6371                                           buffer.data,
6372                                           buffer.length);
6373         }
6374
6375         if (force_update || printer->attributes != old_printer->attributes) {
6376                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6377                 SIVAL(buffer.data, 0, (printer->attributes &
6378                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6379                 winreg_set_printer_dataex(mem_ctx,
6380                                           session_info,
6381                                           msg_ctx,
6382                                           printer->sharename,
6383                                           SPOOL_DSSPOOLER_KEY,
6384                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6385                                           REG_DWORD,
6386                                           buffer.data,
6387                                           buffer.length);
6388
6389                 switch (printer->attributes & 0x3) {
6390                         case 0:
6391                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6392                                 break;
6393                         case 1:
6394                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6395                                 break;
6396                         case 2:
6397                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6398                                 break;
6399                         default:
6400                                 spooling = "unknown";
6401                 }
6402                 push_reg_sz(mem_ctx, &buffer, spooling);
6403                 winreg_set_printer_dataex(mem_ctx,
6404                                           session_info,
6405                                           msg_ctx,
6406                                           printer->sharename,
6407                                           SPOOL_DSSPOOLER_KEY,
6408                                           SPOOL_REG_PRINTSPOOLING,
6409                                           REG_SZ,
6410                                           buffer.data,
6411                                           buffer.length);
6412         }
6413
6414         push_reg_sz(mem_ctx, &buffer, global_myname());
6415         winreg_set_printer_dataex(mem_ctx,
6416                                   session_info,
6417                                   msg_ctx,
6418                                   printer->sharename,
6419                                   SPOOL_DSSPOOLER_KEY,
6420                                   SPOOL_REG_SHORTSERVERNAME,
6421                                   REG_SZ,
6422                                   buffer.data,
6423                                   buffer.length);
6424
6425         dnsdomname = get_mydnsfullname();
6426         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6427                 longname = talloc_strdup(mem_ctx, dnsdomname);
6428         } else {
6429                 longname = talloc_strdup(mem_ctx, global_myname());
6430         }
6431         if (longname == NULL) {
6432                 result = WERR_NOMEM;
6433                 goto done;
6434         }
6435
6436         push_reg_sz(mem_ctx, &buffer, longname);
6437         winreg_set_printer_dataex(mem_ctx,
6438                                   session_info,
6439                                   msg_ctx,
6440                                   printer->sharename,
6441                                   SPOOL_DSSPOOLER_KEY,
6442                                   SPOOL_REG_SERVERNAME,
6443                                   REG_SZ,
6444                                   buffer.data,
6445                                   buffer.length);
6446
6447         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6448                                   global_myname(), printer->sharename);
6449         push_reg_sz(mem_ctx, &buffer, uncname);
6450         winreg_set_printer_dataex(mem_ctx,
6451                                   session_info,
6452                                   msg_ctx,
6453                                   printer->sharename,
6454                                   SPOOL_DSSPOOLER_KEY,
6455                                   SPOOL_REG_UNCNAME,
6456                                   REG_SZ,
6457                                   buffer.data,
6458                                   buffer.length);
6459
6460 done:
6461         return result;
6462 }
6463
6464 /********************************************************************
6465  * Called by spoolss_api_setprinter
6466  * when updating a printer description.
6467  ********************************************************************/
6468
6469 static WERROR update_printer(struct pipes_struct *p,
6470                              struct policy_handle *handle,
6471                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6472                              struct spoolss_DeviceMode *devmode)
6473 {
6474         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6475         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6476         struct spoolss_PrinterInfo2 *old_printer;
6477         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6478         int snum;
6479         WERROR result = WERR_OK;
6480         TALLOC_CTX *tmp_ctx;
6481
6482         DEBUG(8,("update_printer\n"));
6483
6484         tmp_ctx = talloc_new(p->mem_ctx);
6485         if (tmp_ctx == NULL) {
6486                 return WERR_NOMEM;
6487         }
6488
6489         if (!Printer) {
6490                 result = WERR_BADFID;
6491                 goto done;
6492         }
6493
6494         if (!get_printer_snum(p, handle, &snum, NULL)) {
6495                 result = WERR_BADFID;
6496                 goto done;
6497         }
6498
6499         result = winreg_get_printer(tmp_ctx,
6500                                     get_session_info_system(),
6501                                     p->msg_ctx,
6502                                     lp_const_servicename(snum),
6503                                     &old_printer);
6504         if (!W_ERROR_IS_OK(result)) {
6505                 result = WERR_BADFID;
6506                 goto done;
6507         }
6508
6509         /* Do sanity check on the requested changes for Samba */
6510         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6511                 result = WERR_INVALID_PARAM;
6512                 goto done;
6513         }
6514
6515         /* FIXME!!! If the driver has changed we really should verify that
6516            it is installed before doing much else   --jerry */
6517
6518         /* Check calling user has permission to update printer description */
6519         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6520                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6521                 result = WERR_ACCESS_DENIED;
6522                 goto done;
6523         }
6524
6525         /* Call addprinter hook */
6526         /* Check changes to see if this is really needed */
6527
6528         if (*lp_addprinter_cmd() &&
6529                         (!strequal(printer->drivername, old_printer->drivername) ||
6530                          !strequal(printer->comment, old_printer->comment) ||
6531                          !strequal(printer->portname, old_printer->portname) ||
6532                          !strequal(printer->location, old_printer->location)) )
6533         {
6534                 /* add_printer_hook() will call reload_services() */
6535                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6536                                       printer, p->client_id->addr,
6537                                       p->msg_ctx)) {
6538                         result = WERR_ACCESS_DENIED;
6539                         goto done;
6540                 }
6541         }
6542
6543         update_dsspooler(tmp_ctx,
6544                          get_session_info_system(),
6545                          p->msg_ctx,
6546                          snum,
6547                          printer,
6548                          old_printer);
6549
6550         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6551
6552         if (devmode == NULL) {
6553                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6554         }
6555         result = winreg_update_printer(tmp_ctx,
6556                                        get_session_info_system(),
6557                                        p->msg_ctx,
6558                                        printer->sharename,
6559                                        printer_mask,
6560                                        printer,
6561                                        devmode,
6562                                        NULL);
6563
6564 done:
6565         talloc_free(tmp_ctx);
6566
6567         return result;
6568 }
6569
6570 /****************************************************************************
6571 ****************************************************************************/
6572 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6573                                            struct policy_handle *handle,
6574                                            struct spoolss_SetPrinterInfo7 *info7)
6575 {
6576 #ifdef HAVE_ADS
6577         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6578         WERROR result;
6579         int snum;
6580         struct printer_handle *Printer;
6581
6582         if ( lp_security() != SEC_ADS ) {
6583                 return WERR_UNKNOWN_LEVEL;
6584         }
6585
6586         Printer = find_printer_index_by_hnd(p, handle);
6587
6588         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6589
6590         if (!Printer)
6591                 return WERR_BADFID;
6592
6593         if (!get_printer_snum(p, handle, &snum, NULL))
6594                 return WERR_BADFID;
6595
6596         result = winreg_get_printer(p->mem_ctx,
6597                                     get_session_info_system(),
6598                                     p->msg_ctx,
6599                                     lp_servicename(snum),
6600                                     &pinfo2);
6601         if (!W_ERROR_IS_OK(result)) {
6602                 return WERR_BADFID;
6603         }
6604
6605         nt_printer_publish(pinfo2,
6606                            get_session_info_system(),
6607                            p->msg_ctx,
6608                            pinfo2,
6609                            info7->action);
6610
6611         TALLOC_FREE(pinfo2);
6612         return WERR_OK;
6613 #else
6614         return WERR_UNKNOWN_LEVEL;
6615 #endif
6616 }
6617
6618 /********************************************************************
6619  ********************************************************************/
6620
6621 static WERROR update_printer_devmode(struct pipes_struct *p,
6622                                      struct policy_handle *handle,
6623                                      struct spoolss_DeviceMode *devmode)
6624 {
6625         int snum;
6626         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6627         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6628
6629         DEBUG(8,("update_printer_devmode\n"));
6630
6631         if (!Printer) {
6632                 return WERR_BADFID;
6633         }
6634
6635         if (!get_printer_snum(p, handle, &snum, NULL)) {
6636                 return WERR_BADFID;
6637         }
6638
6639         /* Check calling user has permission to update printer description */
6640         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6641                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6642                 return WERR_ACCESS_DENIED;
6643         }
6644
6645         return winreg_update_printer(p->mem_ctx,
6646                                      get_session_info_system(),
6647                                      p->msg_ctx,
6648                                      lp_const_servicename(snum),
6649                                      info2_mask,
6650                                      NULL,
6651                                      devmode,
6652                                      NULL);
6653 }
6654
6655
6656 /****************************************************************
6657  _spoolss_SetPrinter
6658 ****************************************************************/
6659
6660 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6661                            struct spoolss_SetPrinter *r)
6662 {
6663         WERROR result;
6664
6665         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6666
6667         if (!Printer) {
6668                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6669                         OUR_HANDLE(r->in.handle)));
6670                 return WERR_BADFID;
6671         }
6672
6673         /* check the level */
6674         switch (r->in.info_ctr->level) {
6675                 case 0:
6676                         return control_printer(r->in.handle, r->in.command, p);
6677                 case 2:
6678                         result = update_printer(p, r->in.handle,
6679                                                 r->in.info_ctr,
6680                                                 r->in.devmode_ctr->devmode);
6681                         if (!W_ERROR_IS_OK(result))
6682                                 return result;
6683                         if (r->in.secdesc_ctr->sd)
6684                                 result = update_printer_sec(r->in.handle, p,
6685                                                             r->in.secdesc_ctr);
6686                         return result;
6687                 case 3:
6688                         return update_printer_sec(r->in.handle, p,
6689                                                   r->in.secdesc_ctr);
6690                 case 7:
6691                         return publish_or_unpublish_printer(p, r->in.handle,
6692                                                             r->in.info_ctr->info.info7);
6693                 case 8:
6694                         return update_printer_devmode(p, r->in.handle,
6695                                                       r->in.devmode_ctr->devmode);
6696                 default:
6697                         return WERR_UNKNOWN_LEVEL;
6698         }
6699 }
6700
6701 /****************************************************************
6702  _spoolss_FindClosePrinterNotify
6703 ****************************************************************/
6704
6705 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6706                                        struct spoolss_FindClosePrinterNotify *r)
6707 {
6708         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6709
6710         if (!Printer) {
6711                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6712                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6713                 return WERR_BADFID;
6714         }
6715
6716         if (Printer->notify.cli_chan != NULL &&
6717             Printer->notify.cli_chan->active_connections > 0) {
6718                 int snum = -1;
6719
6720                 if (Printer->printer_type == SPLHND_PRINTER) {
6721                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6722                                 return WERR_BADFID;
6723                         }
6724                 }
6725
6726                 srv_spoolss_replycloseprinter(snum, Printer);
6727         }
6728
6729         Printer->notify.flags=0;
6730         Printer->notify.options=0;
6731         Printer->notify.localmachine[0]='\0';
6732         Printer->notify.printerlocal=0;
6733         TALLOC_FREE(Printer->notify.option);
6734
6735         return WERR_OK;
6736 }
6737
6738 /****************************************************************
6739  _spoolss_AddJob
6740 ****************************************************************/
6741
6742 WERROR _spoolss_AddJob(struct pipes_struct *p,
6743                        struct spoolss_AddJob *r)
6744 {
6745         if (!r->in.buffer && (r->in.offered != 0)) {
6746                 return WERR_INVALID_PARAM;
6747         }
6748
6749         /* this is what a NT server returns for AddJob. AddJob must fail on
6750          * non-local printers */
6751
6752         if (r->in.level != 1) {
6753                 return WERR_UNKNOWN_LEVEL;
6754         }
6755
6756         return WERR_INVALID_PARAM;
6757 }
6758
6759 /****************************************************************************
6760 fill_job_info1
6761 ****************************************************************************/
6762
6763 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6764                              struct spoolss_JobInfo1 *r,
6765                              const print_queue_struct *queue,
6766                              int position, int snum,
6767                              struct spoolss_PrinterInfo2 *pinfo2)
6768 {
6769         struct tm *t;
6770
6771         t = gmtime(&queue->time);
6772
6773         r->job_id               = queue->job;
6774
6775         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6776         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6777         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6778         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6779         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6780         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6781         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6782         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6783         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6784         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6785         r->text_status          = talloc_strdup(mem_ctx, "");
6786         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6787
6788         r->status               = nt_printj_status(queue->status);
6789         r->priority             = queue->priority;
6790         r->position             = position;
6791         r->total_pages          = queue->page_count;
6792         r->pages_printed        = 0; /* ??? */
6793
6794         init_systemtime(&r->submitted, t);
6795
6796         return WERR_OK;
6797 }
6798
6799 /****************************************************************************
6800 fill_job_info2
6801 ****************************************************************************/
6802
6803 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6804                              struct spoolss_JobInfo2 *r,
6805                              const print_queue_struct *queue,
6806                              int position, int snum,
6807                              struct spoolss_PrinterInfo2 *pinfo2,
6808                              struct spoolss_DeviceMode *devmode)
6809 {
6810         struct tm *t;
6811
6812         t = gmtime(&queue->time);
6813
6814         r->job_id               = queue->job;
6815
6816         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6817         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6818         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6819         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6820         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6821         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6822         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6823         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6824         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6825         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6826         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6827         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6828         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6829         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6830         r->parameters           = talloc_strdup(mem_ctx, "");
6831         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6832         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6833         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6834
6835         r->devmode              = devmode;
6836
6837         r->text_status          = talloc_strdup(mem_ctx, "");
6838         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6839
6840         r->secdesc              = NULL;
6841
6842         r->status               = nt_printj_status(queue->status);
6843         r->priority             = queue->priority;
6844         r->position             = position;
6845         r->start_time           = 0;
6846         r->until_time           = 0;
6847         r->total_pages          = queue->page_count;
6848         r->size                 = queue->size;
6849         init_systemtime(&r->submitted, t);
6850         r->time                 = 0;
6851         r->pages_printed        = 0; /* ??? */
6852
6853         return WERR_OK;
6854 }
6855
6856 /****************************************************************************
6857 fill_job_info3
6858 ****************************************************************************/
6859
6860 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6861                              struct spoolss_JobInfo3 *r,
6862                              const print_queue_struct *queue,
6863                              const print_queue_struct *next_queue,
6864                              int position, int snum,
6865                              struct spoolss_PrinterInfo2 *pinfo2)
6866 {
6867         r->job_id               = queue->job;
6868         r->next_job_id          = 0;
6869         if (next_queue) {
6870                 r->next_job_id  = next_queue->job;
6871         }
6872         r->reserved             = 0;
6873
6874         return WERR_OK;
6875 }
6876
6877 /****************************************************************************
6878  Enumjobs at level 1.
6879 ****************************************************************************/
6880
6881 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6882                               const print_queue_struct *queue,
6883                               uint32_t num_queues, int snum,
6884                               struct spoolss_PrinterInfo2 *pinfo2,
6885                               union spoolss_JobInfo **info_p,
6886                               uint32_t *count)
6887 {
6888         union spoolss_JobInfo *info;
6889         int i;
6890         WERROR result = WERR_OK;
6891
6892         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6893         W_ERROR_HAVE_NO_MEMORY(info);
6894
6895         *count = num_queues;
6896
6897         for (i=0; i<*count; i++) {
6898                 result = fill_job_info1(info,
6899                                         &info[i].info1,
6900                                         &queue[i],
6901                                         i,
6902                                         snum,
6903                                         pinfo2);
6904                 if (!W_ERROR_IS_OK(result)) {
6905                         goto out;
6906                 }
6907         }
6908
6909  out:
6910         if (!W_ERROR_IS_OK(result)) {
6911                 TALLOC_FREE(info);
6912                 *count = 0;
6913                 return result;
6914         }
6915
6916         *info_p = info;
6917
6918         return WERR_OK;
6919 }
6920
6921 /****************************************************************************
6922  Enumjobs at level 2.
6923 ****************************************************************************/
6924
6925 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6926                               const print_queue_struct *queue,
6927                               uint32_t num_queues, int snum,
6928                               struct spoolss_PrinterInfo2 *pinfo2,
6929                               union spoolss_JobInfo **info_p,
6930                               uint32_t *count)
6931 {
6932         union spoolss_JobInfo *info;
6933         int i;
6934         WERROR result = WERR_OK;
6935
6936         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6937         W_ERROR_HAVE_NO_MEMORY(info);
6938
6939         *count = num_queues;
6940
6941         for (i=0; i<*count; i++) {
6942                 struct spoolss_DeviceMode *devmode;
6943
6944                 result = spoolss_create_default_devmode(info,
6945                                                         pinfo2->printername,
6946                                                         &devmode);
6947                 if (!W_ERROR_IS_OK(result)) {
6948                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6949                         goto out;
6950                 }
6951
6952                 result = fill_job_info2(info,
6953                                         &info[i].info2,
6954                                         &queue[i],
6955                                         i,
6956                                         snum,
6957                                         pinfo2,
6958                                         devmode);
6959                 if (!W_ERROR_IS_OK(result)) {
6960                         goto out;
6961                 }
6962         }
6963
6964  out:
6965         if (!W_ERROR_IS_OK(result)) {
6966                 TALLOC_FREE(info);
6967                 *count = 0;
6968                 return result;
6969         }
6970
6971         *info_p = info;
6972
6973         return WERR_OK;
6974 }
6975
6976 /****************************************************************************
6977  Enumjobs at level 3.
6978 ****************************************************************************/
6979
6980 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6981                               const print_queue_struct *queue,
6982                               uint32_t num_queues, int snum,
6983                               struct spoolss_PrinterInfo2 *pinfo2,
6984                               union spoolss_JobInfo **info_p,
6985                               uint32_t *count)
6986 {
6987         union spoolss_JobInfo *info;
6988         int i;
6989         WERROR result = WERR_OK;
6990
6991         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6992         W_ERROR_HAVE_NO_MEMORY(info);
6993
6994         *count = num_queues;
6995
6996         for (i=0; i<*count; i++) {
6997                 const print_queue_struct *next_queue = NULL;
6998
6999                 if (i+1 < *count) {
7000                         next_queue = &queue[i+1];
7001                 }
7002
7003                 result = fill_job_info3(info,
7004                                         &info[i].info3,
7005                                         &queue[i],
7006                                         next_queue,
7007                                         i,
7008                                         snum,
7009                                         pinfo2);
7010                 if (!W_ERROR_IS_OK(result)) {
7011                         goto out;
7012                 }
7013         }
7014
7015  out:
7016         if (!W_ERROR_IS_OK(result)) {
7017                 TALLOC_FREE(info);
7018                 *count = 0;
7019                 return result;
7020         }
7021
7022         *info_p = info;
7023
7024         return WERR_OK;
7025 }
7026
7027 /****************************************************************
7028  _spoolss_EnumJobs
7029 ****************************************************************/
7030
7031 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7032                          struct spoolss_EnumJobs *r)
7033 {
7034         WERROR result;
7035         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7036         int snum;
7037         print_status_struct prt_status;
7038         print_queue_struct *queue = NULL;
7039         uint32_t count;
7040
7041         /* that's an [in out] buffer */
7042
7043         if (!r->in.buffer && (r->in.offered != 0)) {
7044                 return WERR_INVALID_PARAM;
7045         }
7046
7047         DEBUG(4,("_spoolss_EnumJobs\n"));
7048
7049         *r->out.needed = 0;
7050         *r->out.count = 0;
7051         *r->out.info = NULL;
7052
7053         /* lookup the printer snum and tdb entry */
7054
7055         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7056                 return WERR_BADFID;
7057         }
7058
7059         result = winreg_get_printer(p->mem_ctx,
7060                                     get_session_info_system(),
7061                                     p->msg_ctx,
7062                                     lp_const_servicename(snum),
7063                                     &pinfo2);
7064         if (!W_ERROR_IS_OK(result)) {
7065                 return result;
7066         }
7067
7068         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7069         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7070                 count, prt_status.status, prt_status.message));
7071
7072         if (count == 0) {
7073                 SAFE_FREE(queue);
7074                 TALLOC_FREE(pinfo2);
7075                 return WERR_OK;
7076         }
7077
7078         switch (r->in.level) {
7079         case 1:
7080                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7081                                          pinfo2, r->out.info, r->out.count);
7082                 break;
7083         case 2:
7084                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7085                                          pinfo2, r->out.info, r->out.count);
7086                 break;
7087         case 3:
7088                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7089                                          pinfo2, r->out.info, r->out.count);
7090                 break;
7091         default:
7092                 result = WERR_UNKNOWN_LEVEL;
7093                 break;
7094         }
7095
7096         SAFE_FREE(queue);
7097         TALLOC_FREE(pinfo2);
7098
7099         if (!W_ERROR_IS_OK(result)) {
7100                 return result;
7101         }
7102
7103         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7104                                                      spoolss_EnumJobs,
7105                                                      *r->out.info, r->in.level,
7106                                                      *r->out.count);
7107         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7108         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7109
7110         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7111 }
7112
7113 /****************************************************************
7114  _spoolss_ScheduleJob
7115 ****************************************************************/
7116
7117 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7118                             struct spoolss_ScheduleJob *r)
7119 {
7120         return WERR_OK;
7121 }
7122
7123 /****************************************************************
7124 ****************************************************************/
7125
7126 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7127                                struct messaging_context *msg_ctx,
7128                                const char *printer_name,
7129                                uint32_t job_id,
7130                                struct spoolss_SetJobInfo1 *r)
7131 {
7132         char *old_doc_name;
7133
7134         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7135                 return WERR_BADFID;
7136         }
7137
7138         if (strequal(old_doc_name, r->document_name)) {
7139                 return WERR_OK;
7140         }
7141
7142         if (!print_job_set_name(server_event_context(), msg_ctx,
7143                                 printer_name, job_id, r->document_name)) {
7144                 return WERR_BADFID;
7145         }
7146
7147         return WERR_OK;
7148 }
7149
7150 /****************************************************************
7151  _spoolss_SetJob
7152 ****************************************************************/
7153
7154 WERROR _spoolss_SetJob(struct pipes_struct *p,
7155                        struct spoolss_SetJob *r)
7156 {
7157         const struct auth_serversupplied_info *session_info = p->session_info;
7158         int snum;
7159         WERROR errcode = WERR_BADFUNC;
7160
7161         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7162                 return WERR_BADFID;
7163         }
7164
7165         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7166                 return WERR_INVALID_PRINTER_NAME;
7167         }
7168
7169         switch (r->in.command) {
7170         case SPOOLSS_JOB_CONTROL_CANCEL:
7171         case SPOOLSS_JOB_CONTROL_DELETE:
7172                 errcode = print_job_delete(session_info, p->msg_ctx,
7173                                            snum, r->in.job_id);
7174                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7175                         errcode = WERR_OK;
7176                 }
7177                 break;
7178         case SPOOLSS_JOB_CONTROL_PAUSE:
7179                 if (print_job_pause(session_info, p->msg_ctx,
7180                                     snum, r->in.job_id, &errcode)) {
7181                         errcode = WERR_OK;
7182                 }
7183                 break;
7184         case SPOOLSS_JOB_CONTROL_RESTART:
7185         case SPOOLSS_JOB_CONTROL_RESUME:
7186                 if (print_job_resume(session_info, p->msg_ctx,
7187                                      snum, r->in.job_id, &errcode)) {
7188                         errcode = WERR_OK;
7189                 }
7190                 break;
7191         case 0:
7192                 errcode = WERR_OK;
7193                 break;
7194         default:
7195                 return WERR_UNKNOWN_LEVEL;
7196         }
7197
7198         if (!W_ERROR_IS_OK(errcode)) {
7199                 return errcode;
7200         }
7201
7202         if (r->in.ctr == NULL) {
7203                 return errcode;
7204         }
7205
7206         switch (r->in.ctr->level) {
7207         case 1:
7208                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7209                                            lp_const_servicename(snum),
7210                                            r->in.job_id,
7211                                            r->in.ctr->info.info1);
7212                 break;
7213         case 2:
7214         case 3:
7215         case 4:
7216         default:
7217                 return WERR_UNKNOWN_LEVEL;
7218         }
7219
7220         return errcode;
7221 }
7222
7223 /****************************************************************************
7224  Enumerates all printer drivers by level and architecture.
7225 ****************************************************************************/
7226
7227 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7228                                                        const struct auth_serversupplied_info *session_info,
7229                                                        struct messaging_context *msg_ctx,
7230                                                        const char *servername,
7231                                                        const char *architecture,
7232                                                        uint32_t level,
7233                                                        union spoolss_DriverInfo **info_p,
7234                                                        uint32_t *count_p)
7235 {
7236         int i;
7237         uint32_t version;
7238         struct spoolss_DriverInfo8 *driver;
7239         union spoolss_DriverInfo *info = NULL;
7240         uint32_t count = 0;
7241         WERROR result = WERR_OK;
7242         uint32_t num_drivers;
7243         const char **drivers;
7244
7245         *count_p = 0;
7246         *info_p = NULL;
7247
7248         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7249                 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7250                                                 architecture, version,
7251                                                 &num_drivers, &drivers);
7252                 if (!W_ERROR_IS_OK(result)) {
7253                         goto out;
7254                 }
7255                 DEBUG(4, ("we have:[%d] drivers in environment"
7256                           " [%s] and version [%d]\n",
7257                           num_drivers, architecture, version));
7258
7259                 if (num_drivers != 0) {
7260                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7261                                                     union spoolss_DriverInfo,
7262                                                     count + num_drivers);
7263                         if (!info) {
7264                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7265                                         "failed to enlarge driver info buffer!\n"));
7266                                 result = WERR_NOMEM;
7267                                 goto out;
7268                         }
7269                 }
7270
7271                 for (i = 0; i < num_drivers; i++) {
7272                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7273
7274                         result = winreg_get_driver(mem_ctx, session_info,
7275                                                    msg_ctx,
7276                                                    architecture, drivers[i],
7277                                                    version, &driver);
7278                         if (!W_ERROR_IS_OK(result)) {
7279                                 goto out;
7280                         }
7281
7282                         switch (level) {
7283                         case 1:
7284                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7285                                                                    driver, servername);
7286                                 break;
7287                         case 2:
7288                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7289                                                                    driver, servername);
7290                                 break;
7291                         case 3:
7292                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7293                                                                    driver, servername);
7294                                 break;
7295                         case 4:
7296                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7297                                                                    driver, servername);
7298                                 break;
7299                         case 5:
7300                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7301                                                                    driver, servername);
7302                                 break;
7303                         case 6:
7304                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7305                                                                    driver, servername);
7306                                 break;
7307                         case 8:
7308                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7309                                                                    driver, servername);
7310                                 break;
7311                         default:
7312                                 result = WERR_UNKNOWN_LEVEL;
7313                                 break;
7314                         }
7315
7316                         TALLOC_FREE(driver);
7317
7318                         if (!W_ERROR_IS_OK(result)) {
7319                                 goto out;
7320                         }
7321                 }
7322
7323                 count += num_drivers;
7324                 TALLOC_FREE(drivers);
7325         }
7326
7327  out:
7328         TALLOC_FREE(drivers);
7329
7330         if (!W_ERROR_IS_OK(result)) {
7331                 TALLOC_FREE(info);
7332                 return result;
7333         }
7334
7335         *info_p = info;
7336         *count_p = count;
7337
7338         return WERR_OK;
7339 }
7340
7341 /****************************************************************************
7342  Enumerates all printer drivers by level.
7343 ****************************************************************************/
7344
7345 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7346                                        const struct auth_serversupplied_info *session_info,
7347                                        struct messaging_context *msg_ctx,
7348                                        const char *servername,
7349                                        const char *architecture,
7350                                        uint32_t level,
7351                                        union spoolss_DriverInfo **info_p,
7352                                        uint32_t *count_p)
7353 {
7354         uint32_t a,i;
7355         WERROR result = WERR_OK;
7356
7357         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7358
7359                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7360
7361                         union spoolss_DriverInfo *info = NULL;
7362                         uint32_t count = 0;
7363
7364                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7365                                                                           session_info,
7366                                                                           msg_ctx,
7367                                                                           servername,
7368                                                                           archi_table[a].long_archi,
7369                                                                           level,
7370                                                                           &info,
7371                                                                           &count);
7372                         if (!W_ERROR_IS_OK(result)) {
7373                                 continue;
7374                         }
7375
7376                         for (i=0; i < count; i++) {
7377                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7378                                              info[i], info_p, count_p);
7379                         }
7380                 }
7381
7382                 return result;
7383         }
7384
7385         return enumprinterdrivers_level_by_architecture(mem_ctx,
7386                                                         session_info,
7387                                                         msg_ctx,
7388                                                         servername,
7389                                                         architecture,
7390                                                         level,
7391                                                         info_p,
7392                                                         count_p);
7393 }
7394
7395 /****************************************************************
7396  _spoolss_EnumPrinterDrivers
7397 ****************************************************************/
7398
7399 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7400                                    struct spoolss_EnumPrinterDrivers *r)
7401 {
7402         const char *cservername;
7403         WERROR result;
7404
7405         /* that's an [in out] buffer */
7406
7407         if (!r->in.buffer && (r->in.offered != 0)) {
7408                 return WERR_INVALID_PARAM;
7409         }
7410
7411         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7412
7413         *r->out.needed = 0;
7414         *r->out.count = 0;
7415         *r->out.info = NULL;
7416
7417         cservername = canon_servername(r->in.server);
7418
7419         if (!is_myname_or_ipaddr(cservername)) {
7420                 return WERR_UNKNOWN_PRINTER_DRIVER;
7421         }
7422
7423         result = enumprinterdrivers_level(p->mem_ctx,
7424                                           get_session_info_system(),
7425                                           p->msg_ctx,
7426                                           cservername,
7427                                           r->in.environment,
7428                                           r->in.level,
7429                                           r->out.info,
7430                                           r->out.count);
7431         if (!W_ERROR_IS_OK(result)) {
7432                 return result;
7433         }
7434
7435         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7436                                                      spoolss_EnumPrinterDrivers,
7437                                                      *r->out.info, r->in.level,
7438                                                      *r->out.count);
7439         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7440         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7441
7442         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7443 }
7444
7445 /****************************************************************
7446  _spoolss_EnumForms
7447 ****************************************************************/
7448
7449 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7450                           struct spoolss_EnumForms *r)
7451 {
7452         WERROR result;
7453
7454         *r->out.count = 0;
7455         *r->out.needed = 0;
7456         *r->out.info = NULL;
7457
7458         /* that's an [in out] buffer */
7459
7460         if (!r->in.buffer && (r->in.offered != 0) ) {
7461                 return WERR_INVALID_PARAM;
7462         }
7463
7464         DEBUG(4,("_spoolss_EnumForms\n"));
7465         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7466         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7467
7468         switch (r->in.level) {
7469         case 1:
7470                 result = winreg_printer_enumforms1(p->mem_ctx,
7471                                                    get_session_info_system(),
7472                                                    p->msg_ctx,
7473                                                    r->out.count,
7474                                                    r->out.info);
7475                 break;
7476         default:
7477                 result = WERR_UNKNOWN_LEVEL;
7478                 break;
7479         }
7480
7481         if (!W_ERROR_IS_OK(result)) {
7482                 return result;
7483         }
7484
7485         if (*r->out.count == 0) {
7486                 return WERR_NO_MORE_ITEMS;
7487         }
7488
7489         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7490                                                      spoolss_EnumForms,
7491                                                      *r->out.info, r->in.level,
7492                                                      *r->out.count);
7493         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7494         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7495
7496         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7497 }
7498
7499 /****************************************************************
7500  _spoolss_GetForm
7501 ****************************************************************/
7502
7503 WERROR _spoolss_GetForm(struct pipes_struct *p,
7504                         struct spoolss_GetForm *r)
7505 {
7506         WERROR result;
7507
7508         /* that's an [in out] buffer */
7509
7510         if (!r->in.buffer && (r->in.offered != 0)) {
7511                 return WERR_INVALID_PARAM;
7512         }
7513
7514         DEBUG(4,("_spoolss_GetForm\n"));
7515         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7516         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7517
7518         switch (r->in.level) {
7519         case 1:
7520                 result = winreg_printer_getform1(p->mem_ctx,
7521                                                  get_session_info_system(),
7522                                                  p->msg_ctx,
7523                                                  r->in.form_name,
7524                                                  &r->out.info->info1);
7525                 break;
7526         default:
7527                 result = WERR_UNKNOWN_LEVEL;
7528                 break;
7529         }
7530
7531         if (!W_ERROR_IS_OK(result)) {
7532                 TALLOC_FREE(r->out.info);
7533                 return result;
7534         }
7535
7536         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7537                                                r->out.info, r->in.level);
7538         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7539
7540         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7541 }
7542
7543 /****************************************************************************
7544 ****************************************************************************/
7545
7546 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7547                           struct spoolss_PortInfo1 *r,
7548                           const char *name)
7549 {
7550         r->port_name = talloc_strdup(mem_ctx, name);
7551         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7552
7553         return WERR_OK;
7554 }
7555
7556 /****************************************************************************
7557  TODO: This probably needs distinguish between TCP/IP and Local ports
7558  somehow.
7559 ****************************************************************************/
7560
7561 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7562                           struct spoolss_PortInfo2 *r,
7563                           const char *name)
7564 {
7565         r->port_name = talloc_strdup(mem_ctx, name);
7566         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7567
7568         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7569         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7570
7571         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7572         W_ERROR_HAVE_NO_MEMORY(r->description);
7573
7574         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7575         r->reserved = 0;
7576
7577         return WERR_OK;
7578 }
7579
7580
7581 /****************************************************************************
7582  wrapper around the enumer ports command
7583 ****************************************************************************/
7584
7585 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7586 {
7587         char *cmd = lp_enumports_cmd();
7588         char **qlines = NULL;
7589         char *command = NULL;
7590         int numlines;
7591         int ret;
7592         int fd;
7593
7594         *count = 0;
7595         *lines = NULL;
7596
7597         /* if no hook then just fill in the default port */
7598
7599         if ( !*cmd ) {
7600                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7601                         return WERR_NOMEM;
7602                 }
7603                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7604                         TALLOC_FREE(qlines);
7605                         return WERR_NOMEM;
7606                 }
7607                 qlines[1] = NULL;
7608                 numlines = 1;
7609         }
7610         else {
7611                 /* we have a valid enumport command */
7612
7613                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7614                 if (!command) {
7615                         return WERR_NOMEM;
7616                 }
7617
7618                 DEBUG(10,("Running [%s]\n", command));
7619                 ret = smbrun(command, &fd);
7620                 DEBUG(10,("Returned [%d]\n", ret));
7621                 TALLOC_FREE(command);
7622                 if (ret != 0) {
7623                         if (fd != -1) {
7624                                 close(fd);
7625                         }
7626                         return WERR_ACCESS_DENIED;
7627                 }
7628
7629                 numlines = 0;
7630                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7631                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7632                 close(fd);
7633         }
7634
7635         *count = numlines;
7636         *lines = qlines;
7637
7638         return WERR_OK;
7639 }
7640
7641 /****************************************************************************
7642  enumports level 1.
7643 ****************************************************************************/
7644
7645 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7646                                 union spoolss_PortInfo **info_p,
7647                                 uint32_t *count)
7648 {
7649         union spoolss_PortInfo *info = NULL;
7650         int i=0;
7651         WERROR result = WERR_OK;
7652         char **qlines = NULL;
7653         int numlines = 0;
7654
7655         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7656         if (!W_ERROR_IS_OK(result)) {
7657                 goto out;
7658         }
7659
7660         if (numlines) {
7661                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7662                 if (!info) {
7663                         DEBUG(10,("Returning WERR_NOMEM\n"));
7664                         result = WERR_NOMEM;
7665                         goto out;
7666                 }
7667
7668                 for (i=0; i<numlines; i++) {
7669                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7670                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7671                         if (!W_ERROR_IS_OK(result)) {
7672                                 goto out;
7673                         }
7674                 }
7675         }
7676         TALLOC_FREE(qlines);
7677
7678 out:
7679         if (!W_ERROR_IS_OK(result)) {
7680                 TALLOC_FREE(info);
7681                 TALLOC_FREE(qlines);
7682                 *count = 0;
7683                 *info_p = NULL;
7684                 return result;
7685         }
7686
7687         *info_p = info;
7688         *count = numlines;
7689
7690         return WERR_OK;
7691 }
7692
7693 /****************************************************************************
7694  enumports level 2.
7695 ****************************************************************************/
7696
7697 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7698                                 union spoolss_PortInfo **info_p,
7699                                 uint32_t *count)
7700 {
7701         union spoolss_PortInfo *info = NULL;
7702         int i=0;
7703         WERROR result = WERR_OK;
7704         char **qlines = NULL;
7705         int numlines = 0;
7706
7707         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7708         if (!W_ERROR_IS_OK(result)) {
7709                 goto out;
7710         }
7711
7712         if (numlines) {
7713                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7714                 if (!info) {
7715                         DEBUG(10,("Returning WERR_NOMEM\n"));
7716                         result = WERR_NOMEM;
7717                         goto out;
7718                 }
7719
7720                 for (i=0; i<numlines; i++) {
7721                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7722                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7723                         if (!W_ERROR_IS_OK(result)) {
7724                                 goto out;
7725                         }
7726                 }
7727         }
7728         TALLOC_FREE(qlines);
7729
7730 out:
7731         if (!W_ERROR_IS_OK(result)) {
7732                 TALLOC_FREE(info);
7733                 TALLOC_FREE(qlines);
7734                 *count = 0;
7735                 *info_p = NULL;
7736                 return result;
7737         }
7738
7739         *info_p = info;
7740         *count = numlines;
7741
7742         return WERR_OK;
7743 }
7744
7745 /****************************************************************
7746  _spoolss_EnumPorts
7747 ****************************************************************/
7748
7749 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7750                           struct spoolss_EnumPorts *r)
7751 {
7752         WERROR result;
7753
7754         /* that's an [in out] buffer */
7755
7756         if (!r->in.buffer && (r->in.offered != 0)) {
7757                 return WERR_INVALID_PARAM;
7758         }
7759
7760         DEBUG(4,("_spoolss_EnumPorts\n"));
7761
7762         *r->out.count = 0;
7763         *r->out.needed = 0;
7764         *r->out.info = NULL;
7765
7766         switch (r->in.level) {
7767         case 1:
7768                 result = enumports_level_1(p->mem_ctx, r->out.info,
7769                                            r->out.count);
7770                 break;
7771         case 2:
7772                 result = enumports_level_2(p->mem_ctx, r->out.info,
7773                                            r->out.count);
7774                 break;
7775         default:
7776                 return WERR_UNKNOWN_LEVEL;
7777         }
7778
7779         if (!W_ERROR_IS_OK(result)) {
7780                 return result;
7781         }
7782
7783         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7784                                                      spoolss_EnumPorts,
7785                                                      *r->out.info, r->in.level,
7786                                                      *r->out.count);
7787         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7788         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7789
7790         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7791 }
7792
7793 /****************************************************************************
7794 ****************************************************************************/
7795
7796 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7797                                            const char *server,
7798                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7799                                            struct spoolss_DeviceMode *devmode,
7800                                            struct security_descriptor *secdesc,
7801                                            struct spoolss_UserLevelCtr *user_ctr,
7802                                            struct policy_handle *handle)
7803 {
7804         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7805         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7806         int     snum;
7807         WERROR err = WERR_OK;
7808
7809         /* samba does not have a concept of local, non-shared printers yet, so
7810          * make sure we always setup sharename - gd */
7811         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7812             (info2->printername != NULL && info2->printername[0] != '\0')) {
7813                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7814                         "no sharename has been set, setting printername %s as sharename\n",
7815                         info2->printername));
7816                 info2->sharename = info2->printername;
7817         }
7818
7819         /* check to see if the printer already exists */
7820         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7821                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7822                         info2->sharename));
7823                 return WERR_PRINTER_ALREADY_EXISTS;
7824         }
7825
7826         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7827                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7828                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7829                                 info2->printername));
7830                         return WERR_PRINTER_ALREADY_EXISTS;
7831                 }
7832         }
7833
7834         /* validate printer info struct */
7835         if (!info2->printername || strlen(info2->printername) == 0) {
7836                 return WERR_INVALID_PRINTER_NAME;
7837         }
7838         if (!info2->portname || strlen(info2->portname) == 0) {
7839                 return WERR_UNKNOWN_PORT;
7840         }
7841         if (!info2->drivername || strlen(info2->drivername) == 0) {
7842                 return WERR_UNKNOWN_PRINTER_DRIVER;
7843         }
7844         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7845                 return WERR_UNKNOWN_PRINTPROCESSOR;
7846         }
7847
7848         /* FIXME!!!  smbd should check to see if the driver is installed before
7849            trying to add a printer like this  --jerry */
7850
7851         if (*lp_addprinter_cmd() ) {
7852                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7853                                        info2, p->client_id->addr,
7854                                        p->msg_ctx) ) {
7855                         return WERR_ACCESS_DENIED;
7856                 }
7857         } else {
7858                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7859                         "smb.conf parameter \"addprinter command\" is defined. This"
7860                         "parameter must exist for this call to succeed\n",
7861                         info2->sharename ));
7862         }
7863
7864         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7865                 return WERR_ACCESS_DENIED;
7866         }
7867
7868         /* you must be a printer admin to add a new printer */
7869         if (!print_access_check(p->session_info,
7870                                 p->msg_ctx,
7871                                 snum,
7872                                 PRINTER_ACCESS_ADMINISTER)) {
7873                 return WERR_ACCESS_DENIED;
7874         }
7875
7876         /*
7877          * Do sanity check on the requested changes for Samba.
7878          */
7879
7880         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7881                 return WERR_INVALID_PARAM;
7882         }
7883
7884         if (devmode == NULL) {
7885                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7886         }
7887
7888         update_dsspooler(p->mem_ctx,
7889                          get_session_info_system(),
7890                          p->msg_ctx,
7891                          0,
7892                          info2,
7893                          NULL);
7894
7895         err = winreg_update_printer(p->mem_ctx,
7896                                     get_session_info_system(),
7897                                     p->msg_ctx,
7898                                     info2->sharename,
7899                                     info2_mask,
7900                                     info2,
7901                                     devmode,
7902                                     secdesc);
7903         if (!W_ERROR_IS_OK(err)) {
7904                 return err;
7905         }
7906
7907         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7908         if (!W_ERROR_IS_OK(err)) {
7909                 /* Handle open failed - remove addition. */
7910                 ZERO_STRUCTP(handle);
7911                 return err;
7912         }
7913
7914         return WERR_OK;
7915 }
7916
7917 /****************************************************************
7918  _spoolss_AddPrinterEx
7919 ****************************************************************/
7920
7921 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7922                              struct spoolss_AddPrinterEx *r)
7923 {
7924         switch (r->in.info_ctr->level) {
7925         case 1:
7926                 /* we don't handle yet */
7927                 /* but I know what to do ... */
7928                 return WERR_UNKNOWN_LEVEL;
7929         case 2:
7930                 return spoolss_addprinterex_level_2(p, r->in.server,
7931                                                     r->in.info_ctr,
7932                                                     r->in.devmode_ctr->devmode,
7933                                                     r->in.secdesc_ctr->sd,
7934                                                     r->in.userlevel_ctr,
7935                                                     r->out.handle);
7936         default:
7937                 return WERR_UNKNOWN_LEVEL;
7938         }
7939 }
7940
7941 /****************************************************************
7942  _spoolss_AddPrinter
7943 ****************************************************************/
7944
7945 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7946                            struct spoolss_AddPrinter *r)
7947 {
7948         struct spoolss_AddPrinterEx a;
7949         struct spoolss_UserLevelCtr userlevel_ctr;
7950
7951         ZERO_STRUCT(userlevel_ctr);
7952
7953         userlevel_ctr.level = 1;
7954
7955         a.in.server             = r->in.server;
7956         a.in.info_ctr           = r->in.info_ctr;
7957         a.in.devmode_ctr        = r->in.devmode_ctr;
7958         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7959         a.in.userlevel_ctr      = &userlevel_ctr;
7960         a.out.handle            = r->out.handle;
7961
7962         return _spoolss_AddPrinterEx(p, &a);
7963 }
7964
7965 /****************************************************************
7966  _spoolss_AddPrinterDriverEx
7967 ****************************************************************/
7968
7969 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7970                                    struct spoolss_AddPrinterDriverEx *r)
7971 {
7972         WERROR err = WERR_OK;
7973         const char *driver_name = NULL;
7974         uint32_t version;
7975         const char *fn;
7976
7977         switch (p->opnum) {
7978                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7979                         fn = "_spoolss_AddPrinterDriver";
7980                         break;
7981                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7982                         fn = "_spoolss_AddPrinterDriverEx";
7983                         break;
7984                 default:
7985                         return WERR_INVALID_PARAM;
7986         }
7987
7988         /*
7989          * we only support the semantics of AddPrinterDriver()
7990          * i.e. only copy files that are newer than existing ones
7991          */
7992
7993         if (r->in.flags == 0) {
7994                 return WERR_INVALID_PARAM;
7995         }
7996
7997         if (r->in.flags != APD_COPY_NEW_FILES) {
7998                 return WERR_ACCESS_DENIED;
7999         }
8000
8001         /* FIXME */
8002         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8003                 /* Clever hack from Martin Zielinski <mz@seh.de>
8004                  * to allow downgrade from level 8 (Vista).
8005                  */
8006                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8007                         r->in.info_ctr->level));
8008                 return WERR_UNKNOWN_LEVEL;
8009         }
8010
8011         DEBUG(5,("Cleaning driver's information\n"));
8012         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8013         if (!W_ERROR_IS_OK(err))
8014                 goto done;
8015
8016         DEBUG(5,("Moving driver to final destination\n"));
8017         err = move_driver_to_download_area(p, r->in.info_ctr);
8018         if (!W_ERROR_IS_OK(err)) {
8019                 goto done;
8020         }
8021
8022         err = winreg_add_driver(p->mem_ctx,
8023                                 get_session_info_system(),
8024                                 p->msg_ctx,
8025                                 r->in.info_ctr,
8026                                 &driver_name,
8027                                 &version);
8028         if (!W_ERROR_IS_OK(err)) {
8029                 goto done;
8030         }
8031
8032         /*
8033          * I think this is where he DrvUpgradePrinter() hook would be
8034          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8035          * server.  Right now, we just need to send ourselves a message
8036          * to update each printer bound to this driver.   --jerry
8037          */
8038
8039         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8040                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8041                         fn, driver_name));
8042         }
8043
8044 done:
8045         return err;
8046 }
8047
8048 /****************************************************************
8049  _spoolss_AddPrinterDriver
8050 ****************************************************************/
8051
8052 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8053                                  struct spoolss_AddPrinterDriver *r)
8054 {
8055         struct spoolss_AddPrinterDriverEx a;
8056
8057         switch (r->in.info_ctr->level) {
8058         case 2:
8059         case 3:
8060         case 4:
8061         case 5:
8062                 break;
8063         default:
8064                 return WERR_UNKNOWN_LEVEL;
8065         }
8066
8067         a.in.servername         = r->in.servername;
8068         a.in.info_ctr           = r->in.info_ctr;
8069         a.in.flags              = APD_COPY_NEW_FILES;
8070
8071         return _spoolss_AddPrinterDriverEx(p, &a);
8072 }
8073
8074 /****************************************************************************
8075 ****************************************************************************/
8076
8077 struct _spoolss_paths {
8078         int type;
8079         const char *share;
8080         const char *dir;
8081 };
8082
8083 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8084
8085 static const struct _spoolss_paths spoolss_paths[]= {
8086         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8087         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8088 };
8089
8090 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8091                                           const char *servername,
8092                                           const char *environment,
8093                                           int component,
8094                                           char **path)
8095 {
8096         const char *pservername = NULL;
8097         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8098         const char *short_archi;
8099
8100         *path = NULL;
8101
8102         /* environment may be empty */
8103         if (environment && strlen(environment)) {
8104                 long_archi = environment;
8105         }
8106
8107         /* servername may be empty */
8108         if (servername && strlen(servername)) {
8109                 pservername = canon_servername(servername);
8110
8111                 if (!is_myname_or_ipaddr(pservername)) {
8112                         return WERR_INVALID_PARAM;
8113                 }
8114         }
8115
8116         if (!(short_archi = get_short_archi(long_archi))) {
8117                 return WERR_INVALID_ENVIRONMENT;
8118         }
8119
8120         switch (component) {
8121         case SPOOLSS_PRTPROCS_PATH:
8122         case SPOOLSS_DRIVER_PATH:
8123                 if (pservername) {
8124                         *path = talloc_asprintf(mem_ctx,
8125                                         "\\\\%s\\%s\\%s",
8126                                         pservername,
8127                                         spoolss_paths[component].share,
8128                                         short_archi);
8129                 } else {
8130                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8131                                         SPOOLSS_DEFAULT_SERVER_PATH,
8132                                         spoolss_paths[component].dir,
8133                                         short_archi);
8134                 }
8135                 break;
8136         default:
8137                 return WERR_INVALID_PARAM;
8138         }
8139
8140         if (!*path) {
8141                 return WERR_NOMEM;
8142         }
8143
8144         return WERR_OK;
8145 }
8146
8147 /****************************************************************************
8148 ****************************************************************************/
8149
8150 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8151                                           const char *servername,
8152                                           const char *environment,
8153                                           struct spoolss_DriverDirectoryInfo1 *r)
8154 {
8155         WERROR werr;
8156         char *path = NULL;
8157
8158         werr = compose_spoolss_server_path(mem_ctx,
8159                                            servername,
8160                                            environment,
8161                                            SPOOLSS_DRIVER_PATH,
8162                                            &path);
8163         if (!W_ERROR_IS_OK(werr)) {
8164                 return werr;
8165         }
8166
8167         DEBUG(4,("printer driver directory: [%s]\n", path));
8168
8169         r->directory_name = path;
8170
8171         return WERR_OK;
8172 }
8173
8174 /****************************************************************
8175  _spoolss_GetPrinterDriverDirectory
8176 ****************************************************************/
8177
8178 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8179                                           struct spoolss_GetPrinterDriverDirectory *r)
8180 {
8181         WERROR werror;
8182
8183         /* that's an [in out] buffer */
8184
8185         if (!r->in.buffer && (r->in.offered != 0)) {
8186                 return WERR_INVALID_PARAM;
8187         }
8188
8189         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8190                 r->in.level));
8191
8192         *r->out.needed = 0;
8193
8194         /* r->in.level is ignored */
8195
8196         werror = getprinterdriverdir_level_1(p->mem_ctx,
8197                                              r->in.server,
8198                                              r->in.environment,
8199                                              &r->out.info->info1);
8200         if (!W_ERROR_IS_OK(werror)) {
8201                 TALLOC_FREE(r->out.info);
8202                 return werror;
8203         }
8204
8205         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8206                                                r->out.info, r->in.level);
8207         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8208
8209         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8210 }
8211
8212 /****************************************************************
8213  _spoolss_EnumPrinterData
8214 ****************************************************************/
8215
8216 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8217                                 struct spoolss_EnumPrinterData *r)
8218 {
8219         WERROR result;
8220         struct spoolss_EnumPrinterDataEx r2;
8221         uint32_t count;
8222         struct spoolss_PrinterEnumValues *info, *val = NULL;
8223         uint32_t needed;
8224
8225         r2.in.handle    = r->in.handle;
8226         r2.in.key_name  = "PrinterDriverData";
8227         r2.in.offered   = 0;
8228         r2.out.count    = &count;
8229         r2.out.info     = &info;
8230         r2.out.needed   = &needed;
8231
8232         result = _spoolss_EnumPrinterDataEx(p, &r2);
8233         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8234                 r2.in.offered = needed;
8235                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8236         }
8237         if (!W_ERROR_IS_OK(result)) {
8238                 return result;
8239         }
8240
8241         /*
8242          * The NT machine wants to know the biggest size of value and data
8243          *
8244          * cf: MSDN EnumPrinterData remark section
8245          */
8246
8247         if (!r->in.value_offered && !r->in.data_offered) {
8248                 uint32_t biggest_valuesize = 0;
8249                 uint32_t biggest_datasize = 0;
8250                 int i, name_length;
8251
8252                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8253
8254                 for (i=0; i<count; i++) {
8255
8256                         name_length = strlen(info[i].value_name);
8257                         if (strlen(info[i].value_name) > biggest_valuesize) {
8258                                 biggest_valuesize = name_length;
8259                         }
8260
8261                         if (info[i].data_length > biggest_datasize) {
8262                                 biggest_datasize = info[i].data_length;
8263                         }
8264
8265                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8266                                 biggest_datasize));
8267                 }
8268
8269                 /* the value is an UNICODE string but real_value_size is the length
8270                    in bytes including the trailing 0 */
8271
8272                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8273                 *r->out.data_needed  = biggest_datasize;
8274
8275                 DEBUG(6,("final values: [%d], [%d]\n",
8276                         *r->out.value_needed, *r->out.data_needed));
8277
8278                 return WERR_OK;
8279         }
8280
8281         if (r->in.enum_index < count) {
8282                 val = &info[r->in.enum_index];
8283         }
8284
8285         if (val == NULL) {
8286                 /* out_value should default to "" or else NT4 has
8287                    problems unmarshalling the response */
8288
8289                 if (r->in.value_offered) {
8290                         *r->out.value_needed = 1;
8291                         r->out.value_name = talloc_strdup(r, "");
8292                         if (!r->out.value_name) {
8293                                 return WERR_NOMEM;
8294                         }
8295                 } else {
8296                         r->out.value_name = NULL;
8297                         *r->out.value_needed = 0;
8298                 }
8299
8300                 /* the data is counted in bytes */
8301
8302                 *r->out.data_needed = r->in.data_offered;
8303
8304                 result = WERR_NO_MORE_ITEMS;
8305         } else {
8306                 /*
8307                  * the value is:
8308                  * - counted in bytes in the request
8309                  * - counted in UNICODE chars in the max reply
8310                  * - counted in bytes in the real size
8311                  *
8312                  * take a pause *before* coding not *during* coding
8313                  */
8314
8315                 /* name */
8316                 if (r->in.value_offered) {
8317                         r->out.value_name = talloc_strdup(r, val->value_name);
8318                         if (!r->out.value_name) {
8319                                 return WERR_NOMEM;
8320                         }
8321                         *r->out.value_needed = val->value_name_len;
8322                 } else {
8323                         r->out.value_name = NULL;
8324                         *r->out.value_needed = 0;
8325                 }
8326
8327                 /* type */
8328
8329                 *r->out.type = val->type;
8330
8331                 /* data - counted in bytes */
8332
8333                 /*
8334                  * See the section "Dynamically Typed Query Parameters"
8335                  * in MS-RPRN.
8336                  */
8337
8338                 if (r->out.data && val->data && val->data->data &&
8339                                 val->data_length && r->in.data_offered) {
8340                         memcpy(r->out.data, val->data->data,
8341                                 MIN(val->data_length,r->in.data_offered));
8342                 }
8343
8344                 *r->out.data_needed = val->data_length;
8345
8346                 result = WERR_OK;
8347         }
8348
8349         return result;
8350 }
8351
8352 /****************************************************************
8353  _spoolss_SetPrinterData
8354 ****************************************************************/
8355
8356 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8357                                struct spoolss_SetPrinterData *r)
8358 {
8359         struct spoolss_SetPrinterDataEx r2;
8360
8361         r2.in.handle            = r->in.handle;
8362         r2.in.key_name          = "PrinterDriverData";
8363         r2.in.value_name        = r->in.value_name;
8364         r2.in.type              = r->in.type;
8365         r2.in.data              = r->in.data;
8366         r2.in.offered           = r->in.offered;
8367
8368         return _spoolss_SetPrinterDataEx(p, &r2);
8369 }
8370
8371 /****************************************************************
8372  _spoolss_ResetPrinter
8373 ****************************************************************/
8374
8375 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8376                              struct spoolss_ResetPrinter *r)
8377 {
8378         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8379         int             snum;
8380
8381         DEBUG(5,("_spoolss_ResetPrinter\n"));
8382
8383         /*
8384          * All we do is to check to see if the handle and queue is valid.
8385          * This call really doesn't mean anything to us because we only
8386          * support RAW printing.   --jerry
8387          */
8388
8389         if (!Printer) {
8390                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8391                         OUR_HANDLE(r->in.handle)));
8392                 return WERR_BADFID;
8393         }
8394
8395         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8396                 return WERR_BADFID;
8397
8398
8399         /* blindly return success */
8400         return WERR_OK;
8401 }
8402
8403 /****************************************************************
8404  _spoolss_DeletePrinterData
8405 ****************************************************************/
8406
8407 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8408                                   struct spoolss_DeletePrinterData *r)
8409 {
8410         struct spoolss_DeletePrinterDataEx r2;
8411
8412         r2.in.handle            = r->in.handle;
8413         r2.in.key_name          = "PrinterDriverData";
8414         r2.in.value_name        = r->in.value_name;
8415
8416         return _spoolss_DeletePrinterDataEx(p, &r2);
8417 }
8418
8419 /****************************************************************
8420  _spoolss_AddForm
8421 ****************************************************************/
8422
8423 WERROR _spoolss_AddForm(struct pipes_struct *p,
8424                         struct spoolss_AddForm *r)
8425 {
8426         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8427         int snum = -1;
8428         WERROR status = WERR_OK;
8429
8430         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8431
8432         DEBUG(5,("_spoolss_AddForm\n"));
8433
8434         if (!Printer) {
8435                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8436                         OUR_HANDLE(r->in.handle)));
8437                 return WERR_BADFID;
8438         }
8439
8440         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8441            and not a printer admin, then fail */
8442
8443         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8444             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8445             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8446                                           p->session_info->info3->base.domain.string,
8447                                           NULL,
8448                                           p->session_info->security_token,
8449                                           lp_printer_admin(snum))) {
8450                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8451                 return WERR_ACCESS_DENIED;
8452         }
8453
8454         switch (form->flags) {
8455         case SPOOLSS_FORM_USER:
8456         case SPOOLSS_FORM_BUILTIN:
8457         case SPOOLSS_FORM_PRINTER:
8458                 break;
8459         default:
8460                 return WERR_INVALID_PARAM;
8461         }
8462
8463         status = winreg_printer_addform1(p->mem_ctx,
8464                                          get_session_info_system(),
8465                                          p->msg_ctx,
8466                                          form);
8467         if (!W_ERROR_IS_OK(status)) {
8468                 return status;
8469         }
8470
8471         /*
8472          * ChangeID must always be set if this is a printer
8473          */
8474         if (Printer->printer_type == SPLHND_PRINTER) {
8475                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8476                         return WERR_BADFID;
8477                 }
8478
8479                 status = winreg_printer_update_changeid(p->mem_ctx,
8480                                                         get_session_info_system(),
8481                                                         p->msg_ctx,
8482                                                         lp_const_servicename(snum));
8483                 if (!W_ERROR_IS_OK(status)) {
8484                         return status;
8485                 }
8486         }
8487
8488         return status;
8489 }
8490
8491 /****************************************************************
8492  _spoolss_DeleteForm
8493 ****************************************************************/
8494
8495 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8496                            struct spoolss_DeleteForm *r)
8497 {
8498         const char *form_name = r->in.form_name;
8499         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8500         int snum = -1;
8501         WERROR status = WERR_OK;
8502
8503         DEBUG(5,("_spoolss_DeleteForm\n"));
8504
8505         if (!Printer) {
8506                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8507                         OUR_HANDLE(r->in.handle)));
8508                 return WERR_BADFID;
8509         }
8510
8511         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8512             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8513             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8514                                           p->session_info->info3->base.domain.string,
8515                                           NULL,
8516                                           p->session_info->security_token,
8517                                           lp_printer_admin(snum))) {
8518                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8519                 return WERR_ACCESS_DENIED;
8520         }
8521
8522         status = winreg_printer_deleteform1(p->mem_ctx,
8523                                             get_session_info_system(),
8524                                             p->msg_ctx,
8525                                             form_name);
8526         if (!W_ERROR_IS_OK(status)) {
8527                 return status;
8528         }
8529
8530         /*
8531          * ChangeID must always be set if this is a printer
8532          */
8533         if (Printer->printer_type == SPLHND_PRINTER) {
8534                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8535                         return WERR_BADFID;
8536                 }
8537
8538                 status = winreg_printer_update_changeid(p->mem_ctx,
8539                                                         get_session_info_system(),
8540                                                         p->msg_ctx,
8541                                                         lp_const_servicename(snum));
8542                 if (!W_ERROR_IS_OK(status)) {
8543                         return status;
8544                 }
8545         }
8546
8547         return status;
8548 }
8549
8550 /****************************************************************
8551  _spoolss_SetForm
8552 ****************************************************************/
8553
8554 WERROR _spoolss_SetForm(struct pipes_struct *p,
8555                         struct spoolss_SetForm *r)
8556 {
8557         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8558         const char *form_name = r->in.form_name;
8559         int snum = -1;
8560         WERROR status = WERR_OK;
8561
8562         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8563
8564         DEBUG(5,("_spoolss_SetForm\n"));
8565
8566         if (!Printer) {
8567                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8568                         OUR_HANDLE(r->in.handle)));
8569                 return WERR_BADFID;
8570         }
8571
8572         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8573            and not a printer admin, then fail */
8574
8575         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8576              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8577              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8578                                           p->session_info->info3->base.domain.string,
8579                                           NULL,
8580                                           p->session_info->security_token,
8581                                           lp_printer_admin(snum))) {
8582                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8583                 return WERR_ACCESS_DENIED;
8584         }
8585
8586         status = winreg_printer_setform1(p->mem_ctx,
8587                                          get_session_info_system(),
8588                                          p->msg_ctx,
8589                                          form_name,
8590                                          form);
8591         if (!W_ERROR_IS_OK(status)) {
8592                 return status;
8593         }
8594
8595         /*
8596          * ChangeID must always be set if this is a printer
8597          */
8598         if (Printer->printer_type == SPLHND_PRINTER) {
8599                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8600                         return WERR_BADFID;
8601                 }
8602
8603                 status = winreg_printer_update_changeid(p->mem_ctx,
8604                                                         get_session_info_system(),
8605                                                         p->msg_ctx,
8606                                                         lp_const_servicename(snum));
8607                 if (!W_ERROR_IS_OK(status)) {
8608                         return status;
8609                 }
8610         }
8611
8612         return status;
8613 }
8614
8615 /****************************************************************************
8616  fill_print_processor1
8617 ****************************************************************************/
8618
8619 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8620                                     struct spoolss_PrintProcessorInfo1 *r,
8621                                     const char *print_processor_name)
8622 {
8623         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8624         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8625
8626         return WERR_OK;
8627 }
8628
8629 /****************************************************************************
8630  enumprintprocessors level 1.
8631 ****************************************************************************/
8632
8633 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8634                                           union spoolss_PrintProcessorInfo **info_p,
8635                                           uint32_t *count)
8636 {
8637         union spoolss_PrintProcessorInfo *info;
8638         WERROR result;
8639
8640         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8641         W_ERROR_HAVE_NO_MEMORY(info);
8642
8643         *count = 1;
8644
8645         result = fill_print_processor1(info, &info[0].info1, "winprint");
8646         if (!W_ERROR_IS_OK(result)) {
8647                 goto out;
8648         }
8649
8650  out:
8651         if (!W_ERROR_IS_OK(result)) {
8652                 TALLOC_FREE(info);
8653                 *count = 0;
8654                 return result;
8655         }
8656
8657         *info_p = info;
8658
8659         return WERR_OK;
8660 }
8661
8662 /****************************************************************
8663  _spoolss_EnumPrintProcessors
8664 ****************************************************************/
8665
8666 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8667                                     struct spoolss_EnumPrintProcessors *r)
8668 {
8669         WERROR result;
8670
8671         /* that's an [in out] buffer */
8672
8673         if (!r->in.buffer && (r->in.offered != 0)) {
8674                 return WERR_INVALID_PARAM;
8675         }
8676
8677         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8678
8679         /*
8680          * Enumerate the print processors ...
8681          *
8682          * Just reply with "winprint", to keep NT happy
8683          * and I can use my nice printer checker.
8684          */
8685
8686         *r->out.count = 0;
8687         *r->out.needed = 0;
8688         *r->out.info = NULL;
8689
8690         if (!get_short_archi(r->in.environment)) {
8691                 return WERR_INVALID_ENVIRONMENT;
8692         }
8693
8694         switch (r->in.level) {
8695         case 1:
8696                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8697                                                      r->out.count);
8698                 break;
8699         default:
8700                 return WERR_UNKNOWN_LEVEL;
8701         }
8702
8703         if (!W_ERROR_IS_OK(result)) {
8704                 return result;
8705         }
8706
8707         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8708                                                      spoolss_EnumPrintProcessors,
8709                                                      *r->out.info, r->in.level,
8710                                                      *r->out.count);
8711         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8712         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8713
8714         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8715 }
8716
8717 /****************************************************************************
8718  fill_printprocdatatype1
8719 ****************************************************************************/
8720
8721 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8722                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8723                                       const char *name_array)
8724 {
8725         r->name_array = talloc_strdup(mem_ctx, name_array);
8726         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8727
8728         return WERR_OK;
8729 }
8730
8731 /****************************************************************************
8732  enumprintprocdatatypes level 1.
8733 ****************************************************************************/
8734
8735 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8736                                              union spoolss_PrintProcDataTypesInfo **info_p,
8737                                              uint32_t *count)
8738 {
8739         WERROR result;
8740         union spoolss_PrintProcDataTypesInfo *info;
8741
8742         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8743         W_ERROR_HAVE_NO_MEMORY(info);
8744
8745         *count = 1;
8746
8747         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8748         if (!W_ERROR_IS_OK(result)) {
8749                 goto out;
8750         }
8751
8752  out:
8753         if (!W_ERROR_IS_OK(result)) {
8754                 TALLOC_FREE(info);
8755                 *count = 0;
8756                 return result;
8757         }
8758
8759         *info_p = info;
8760
8761         return WERR_OK;
8762 }
8763
8764 /****************************************************************
8765  _spoolss_EnumPrintProcDataTypes
8766 ****************************************************************/
8767
8768 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8769                                        struct spoolss_EnumPrintProcDataTypes *r)
8770 {
8771         WERROR result;
8772
8773         /* that's an [in out] buffer */
8774
8775         if (!r->in.buffer && (r->in.offered != 0)) {
8776                 return WERR_INVALID_PARAM;
8777         }
8778
8779         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8780
8781         *r->out.count = 0;
8782         *r->out.needed = 0;
8783         *r->out.info = NULL;
8784
8785         if (r->in.print_processor_name == NULL ||
8786             !strequal(r->in.print_processor_name, "winprint")) {
8787                 return WERR_UNKNOWN_PRINTPROCESSOR;
8788         }
8789
8790         switch (r->in.level) {
8791         case 1:
8792                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8793                                                         r->out.count);
8794                 break;
8795         default:
8796                 return WERR_UNKNOWN_LEVEL;
8797         }
8798
8799         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8800                                                      spoolss_EnumPrintProcDataTypes,
8801                                                      *r->out.info, r->in.level,
8802                                                      *r->out.count);
8803         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8804         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8805
8806         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8807 }
8808
8809 /****************************************************************************
8810  fill_monitor_1
8811 ****************************************************************************/
8812
8813 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8814                              struct spoolss_MonitorInfo1 *r,
8815                              const char *monitor_name)
8816 {
8817         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8818         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8819
8820         return WERR_OK;
8821 }
8822
8823 /****************************************************************************
8824  fill_monitor_2
8825 ****************************************************************************/
8826
8827 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8828                              struct spoolss_MonitorInfo2 *r,
8829                              const char *monitor_name,
8830                              const char *environment,
8831                              const char *dll_name)
8832 {
8833         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8834         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8835         r->environment                  = talloc_strdup(mem_ctx, environment);
8836         W_ERROR_HAVE_NO_MEMORY(r->environment);
8837         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8838         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8839
8840         return WERR_OK;
8841 }
8842
8843 /****************************************************************************
8844  enumprintmonitors level 1.
8845 ****************************************************************************/
8846
8847 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8848                                         union spoolss_MonitorInfo **info_p,
8849                                         uint32_t *count)
8850 {
8851         union spoolss_MonitorInfo *info;
8852         WERROR result = WERR_OK;
8853
8854         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8855         W_ERROR_HAVE_NO_MEMORY(info);
8856
8857         *count = 2;
8858
8859         result = fill_monitor_1(info, &info[0].info1,
8860                                 SPL_LOCAL_PORT);
8861         if (!W_ERROR_IS_OK(result)) {
8862                 goto out;
8863         }
8864
8865         result = fill_monitor_1(info, &info[1].info1,
8866                                 SPL_TCPIP_PORT);
8867         if (!W_ERROR_IS_OK(result)) {
8868                 goto out;
8869         }
8870
8871 out:
8872         if (!W_ERROR_IS_OK(result)) {
8873                 TALLOC_FREE(info);
8874                 *count = 0;
8875                 return result;
8876         }
8877
8878         *info_p = info;
8879
8880         return WERR_OK;
8881 }
8882
8883 /****************************************************************************
8884  enumprintmonitors level 2.
8885 ****************************************************************************/
8886
8887 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8888                                         union spoolss_MonitorInfo **info_p,
8889                                         uint32_t *count)
8890 {
8891         union spoolss_MonitorInfo *info;
8892         WERROR result = WERR_OK;
8893
8894         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8895         W_ERROR_HAVE_NO_MEMORY(info);
8896
8897         *count = 2;
8898
8899         result = fill_monitor_2(info, &info[0].info2,
8900                                 SPL_LOCAL_PORT,
8901                                 "Windows NT X86", /* FIXME */
8902                                 "localmon.dll");
8903         if (!W_ERROR_IS_OK(result)) {
8904                 goto out;
8905         }
8906
8907         result = fill_monitor_2(info, &info[1].info2,
8908                                 SPL_TCPIP_PORT,
8909                                 "Windows NT X86", /* FIXME */
8910                                 "tcpmon.dll");
8911         if (!W_ERROR_IS_OK(result)) {
8912                 goto out;
8913         }
8914
8915 out:
8916         if (!W_ERROR_IS_OK(result)) {
8917                 TALLOC_FREE(info);
8918                 *count = 0;
8919                 return result;
8920         }
8921
8922         *info_p = info;
8923
8924         return WERR_OK;
8925 }
8926
8927 /****************************************************************
8928  _spoolss_EnumMonitors
8929 ****************************************************************/
8930
8931 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8932                              struct spoolss_EnumMonitors *r)
8933 {
8934         WERROR result;
8935
8936         /* that's an [in out] buffer */
8937
8938         if (!r->in.buffer && (r->in.offered != 0)) {
8939                 return WERR_INVALID_PARAM;
8940         }
8941
8942         DEBUG(5,("_spoolss_EnumMonitors\n"));
8943
8944         /*
8945          * Enumerate the print monitors ...
8946          *
8947          * Just reply with "Local Port", to keep NT happy
8948          * and I can use my nice printer checker.
8949          */
8950
8951         *r->out.count = 0;
8952         *r->out.needed = 0;
8953         *r->out.info = NULL;
8954
8955         switch (r->in.level) {
8956         case 1:
8957                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8958                                                    r->out.count);
8959                 break;
8960         case 2:
8961                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8962                                                    r->out.count);
8963                 break;
8964         default:
8965                 return WERR_UNKNOWN_LEVEL;
8966         }
8967
8968         if (!W_ERROR_IS_OK(result)) {
8969                 return result;
8970         }
8971
8972         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8973                                                      spoolss_EnumMonitors,
8974                                                      *r->out.info, r->in.level,
8975                                                      *r->out.count);
8976         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8977         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8978
8979         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8980 }
8981
8982 /****************************************************************************
8983 ****************************************************************************/
8984
8985 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8986                              const print_queue_struct *queue,
8987                              int count, int snum,
8988                              struct spoolss_PrinterInfo2 *pinfo2,
8989                              uint32_t jobid,
8990                              struct spoolss_JobInfo1 *r)
8991 {
8992         int i = 0;
8993         bool found = false;
8994
8995         for (i=0; i<count; i++) {
8996                 if (queue[i].job == (int)jobid) {
8997                         found = true;
8998                         break;
8999                 }
9000         }
9001
9002         if (found == false) {
9003                 /* NT treats not found as bad param... yet another bad choice */
9004                 return WERR_INVALID_PARAM;
9005         }
9006
9007         return fill_job_info1(mem_ctx,
9008                               r,
9009                               &queue[i],
9010                               i,
9011                               snum,
9012                               pinfo2);
9013 }
9014
9015 /****************************************************************************
9016 ****************************************************************************/
9017
9018 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9019                              const print_queue_struct *queue,
9020                              int count, int snum,
9021                              struct spoolss_PrinterInfo2 *pinfo2,
9022                              uint32_t jobid,
9023                              struct spoolss_JobInfo2 *r)
9024 {
9025         int i = 0;
9026         bool found = false;
9027         struct spoolss_DeviceMode *devmode;
9028         WERROR result;
9029
9030         for (i=0; i<count; i++) {
9031                 if (queue[i].job == (int)jobid) {
9032                         found = true;
9033                         break;
9034                 }
9035         }
9036
9037         if (found == false) {
9038                 /* NT treats not found as bad param... yet another bad
9039                    choice */
9040                 return WERR_INVALID_PARAM;
9041         }
9042
9043         /*
9044          * if the print job does not have a DEVMODE associated with it,
9045          * just use the one for the printer. A NULL devicemode is not
9046          *  a failure condition
9047          */
9048
9049         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9050         if (!devmode) {
9051                 result = spoolss_create_default_devmode(mem_ctx,
9052                                                 pinfo2->printername,
9053                                                 &devmode);
9054                 if (!W_ERROR_IS_OK(result)) {
9055                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9056                         return result;
9057                 }
9058         }
9059
9060         return fill_job_info2(mem_ctx,
9061                               r,
9062                               &queue[i],
9063                               i,
9064                               snum,
9065                               pinfo2,
9066                               devmode);
9067 }
9068
9069 /****************************************************************
9070  _spoolss_GetJob
9071 ****************************************************************/
9072
9073 WERROR _spoolss_GetJob(struct pipes_struct *p,
9074                        struct spoolss_GetJob *r)
9075 {
9076         WERROR result = WERR_OK;
9077         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9078         int snum;
9079         int count;
9080         print_queue_struct      *queue = NULL;
9081         print_status_struct prt_status;
9082
9083         /* that's an [in out] buffer */
9084
9085         if (!r->in.buffer && (r->in.offered != 0)) {
9086                 return WERR_INVALID_PARAM;
9087         }
9088
9089         DEBUG(5,("_spoolss_GetJob\n"));
9090
9091         *r->out.needed = 0;
9092
9093         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9094                 return WERR_BADFID;
9095         }
9096
9097         result = winreg_get_printer(p->mem_ctx,
9098                                     get_session_info_system(),
9099                                     p->msg_ctx,
9100                                     lp_const_servicename(snum),
9101                                     &pinfo2);
9102         if (!W_ERROR_IS_OK(result)) {
9103                 return result;
9104         }
9105
9106         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9107
9108         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9109                      count, prt_status.status, prt_status.message));
9110
9111         switch (r->in.level) {
9112         case 1:
9113                 result = getjob_level_1(p->mem_ctx,
9114                                         queue, count, snum, pinfo2,
9115                                         r->in.job_id, &r->out.info->info1);
9116                 break;
9117         case 2:
9118                 result = getjob_level_2(p->mem_ctx,
9119                                         queue, count, snum, pinfo2,
9120                                         r->in.job_id, &r->out.info->info2);
9121                 break;
9122         default:
9123                 result = WERR_UNKNOWN_LEVEL;
9124                 break;
9125         }
9126
9127         SAFE_FREE(queue);
9128         TALLOC_FREE(pinfo2);
9129
9130         if (!W_ERROR_IS_OK(result)) {
9131                 TALLOC_FREE(r->out.info);
9132                 return result;
9133         }
9134
9135         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9136                                                                                    r->in.level);
9137         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9138
9139         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9140 }
9141
9142 /****************************************************************
9143  _spoolss_GetPrinterDataEx
9144 ****************************************************************/
9145
9146 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9147                                  struct spoolss_GetPrinterDataEx *r)
9148 {
9149
9150         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9151         const char *printer;
9152         int                     snum = 0;
9153         WERROR result = WERR_OK;
9154         DATA_BLOB blob;
9155         enum winreg_Type val_type;
9156         uint8_t *val_data;
9157         uint32_t val_size;
9158
9159
9160         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9161
9162         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9163                 r->in.key_name, r->in.value_name));
9164
9165         /* in case of problem, return some default values */
9166
9167         *r->out.needed  = 0;
9168         *r->out.type    = REG_NONE;
9169
9170         if (!Printer) {
9171                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9172                         OUR_HANDLE(r->in.handle)));
9173                 result = WERR_BADFID;
9174                 goto done;
9175         }
9176
9177         /* Is the handle to a printer or to the server? */
9178
9179         if (Printer->printer_type == SPLHND_SERVER) {
9180
9181                 union spoolss_PrinterData data;
9182
9183                 result = getprinterdata_printer_server(p->mem_ctx,
9184                                                        r->in.value_name,
9185                                                        r->out.type,
9186                                                        &data);
9187                 if (!W_ERROR_IS_OK(result)) {
9188                         return result;
9189                 }
9190
9191                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9192                                                   *r->out.type, &data);
9193                 if (!W_ERROR_IS_OK(result)) {
9194                         return result;
9195                 }
9196
9197                 *r->out.needed = blob.length;
9198
9199                 if (r->in.offered >= *r->out.needed) {
9200                         memcpy(r->out.data, blob.data, blob.length);
9201                 }
9202
9203                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9204         }
9205
9206         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9207                 return WERR_BADFID;
9208         }
9209         printer = lp_const_servicename(snum);
9210
9211         /* check to see if the keyname is valid */
9212         if (!strlen(r->in.key_name)) {
9213                 return WERR_INVALID_PARAM;
9214         }
9215
9216         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9217         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9218             strequal(r->in.value_name, "ChangeId")) {
9219                 *r->out.type = REG_DWORD;
9220                 *r->out.needed = 4;
9221                 if (r->in.offered >= *r->out.needed) {
9222                         uint32_t changeid = 0;
9223
9224                         result = winreg_printer_get_changeid(p->mem_ctx,
9225                                                              get_session_info_system(),
9226                                                              p->msg_ctx,
9227                                                              printer,
9228                                                              &changeid);
9229                         if (!W_ERROR_IS_OK(result)) {
9230                                 return result;
9231                         }
9232
9233                         SIVAL(r->out.data, 0, changeid);
9234                         result = WERR_OK;
9235                 }
9236                 goto done;
9237         }
9238
9239         result = winreg_get_printer_dataex(p->mem_ctx,
9240                                            get_session_info_system(),
9241                                            p->msg_ctx,
9242                                            printer,
9243                                            r->in.key_name,
9244                                            r->in.value_name,
9245                                            &val_type,
9246                                            &val_data,
9247                                            &val_size);
9248         if (!W_ERROR_IS_OK(result)) {
9249                 return result;
9250         }
9251
9252         *r->out.needed = val_size;
9253         *r->out.type = val_type;
9254
9255         if (r->in.offered >= *r->out.needed) {
9256                 memcpy(r->out.data, val_data, val_size);
9257         }
9258
9259  done:
9260         /* retain type when returning WERR_MORE_DATA */
9261         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9262
9263         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9264 }
9265
9266 /****************************************************************
9267  _spoolss_SetPrinterDataEx
9268 ****************************************************************/
9269
9270 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9271                                  struct spoolss_SetPrinterDataEx *r)
9272 {
9273         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9274         int                     snum = 0;
9275         WERROR                  result = WERR_OK;
9276         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9277         char                    *oid_string;
9278
9279         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9280
9281         /* From MSDN documentation of SetPrinterDataEx: pass request to
9282            SetPrinterData if key is "PrinterDriverData" */
9283
9284         if (!Printer) {
9285                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9286                         OUR_HANDLE(r->in.handle)));
9287                 return WERR_BADFID;
9288         }
9289
9290         if (Printer->printer_type == SPLHND_SERVER) {
9291                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9292                         "Not implemented for server handles yet\n"));
9293                 return WERR_INVALID_PARAM;
9294         }
9295
9296         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9297                 return WERR_BADFID;
9298         }
9299
9300         /*
9301          * Access check : NT returns "access denied" if you make a
9302          * SetPrinterData call without the necessary privildge.
9303          * we were originally returning OK if nothing changed
9304          * which made Win2k issue **a lot** of SetPrinterData
9305          * when connecting to a printer  --jerry
9306          */
9307
9308         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9309                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9310                         "change denied by handle access permissions\n"));
9311                 return WERR_ACCESS_DENIED;
9312         }
9313
9314         result = winreg_get_printer(Printer,
9315                                     get_session_info_system(),
9316                                     p->msg_ctx,
9317                                     lp_servicename(snum),
9318                                     &pinfo2);
9319         if (!W_ERROR_IS_OK(result)) {
9320                 return result;
9321         }
9322
9323         /* check for OID in valuename */
9324
9325         oid_string = strchr(r->in.value_name, ',');
9326         if (oid_string) {
9327                 *oid_string = '\0';
9328                 oid_string++;
9329         }
9330
9331         /* save the registry data */
9332
9333         result = winreg_set_printer_dataex(p->mem_ctx,
9334                                            get_session_info_system(),
9335                                            p->msg_ctx,
9336                                            pinfo2->sharename,
9337                                            r->in.key_name,
9338                                            r->in.value_name,
9339                                            r->in.type,
9340                                            r->in.data,
9341                                            r->in.offered);
9342
9343         if (W_ERROR_IS_OK(result)) {
9344                 /* save the OID if one was specified */
9345                 if (oid_string) {
9346                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9347                                 r->in.key_name, SPOOL_OID_KEY);
9348                         if (!str) {
9349                                 result = WERR_NOMEM;
9350                                 goto done;
9351                         }
9352
9353                         /*
9354                          * I'm not checking the status here on purpose.  Don't know
9355                          * if this is right, but I'm returning the status from the
9356                          * previous set_printer_dataex() call.  I have no idea if
9357                          * this is right.    --jerry
9358                          */
9359                         winreg_set_printer_dataex(p->mem_ctx,
9360                                                   get_session_info_system(),
9361                                                   p->msg_ctx,
9362                                                   pinfo2->sharename,
9363                                                   str,
9364                                                   r->in.value_name,
9365                                                   REG_SZ,
9366                                                   (uint8_t *) oid_string,
9367                                                   strlen(oid_string) + 1);
9368                 }
9369
9370                 result = winreg_printer_update_changeid(p->mem_ctx,
9371                                                         get_session_info_system(),
9372                                                         p->msg_ctx,
9373                                                         lp_const_servicename(snum));
9374
9375         }
9376
9377 done:
9378         talloc_free(pinfo2);
9379         return result;
9380 }
9381
9382 /****************************************************************
9383  _spoolss_DeletePrinterDataEx
9384 ****************************************************************/
9385
9386 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9387                                     struct spoolss_DeletePrinterDataEx *r)
9388 {
9389         const char *printer;
9390         int             snum=0;
9391         WERROR          status = WERR_OK;
9392         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9393
9394         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9395
9396         if (!Printer) {
9397                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9398                         "Invalid handle (%s:%u:%u).\n",
9399                         OUR_HANDLE(r->in.handle)));
9400                 return WERR_BADFID;
9401         }
9402
9403         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9404                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9405                         "printer properties change denied by handle\n"));
9406                 return WERR_ACCESS_DENIED;
9407         }
9408
9409         if (!r->in.value_name || !r->in.key_name) {
9410                 return WERR_NOMEM;
9411         }
9412
9413         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9414                 return WERR_BADFID;
9415         }
9416         printer = lp_const_servicename(snum);
9417
9418         status = winreg_delete_printer_dataex(p->mem_ctx,
9419                                               get_session_info_system(),
9420                                               p->msg_ctx,
9421                                               printer,
9422                                               r->in.key_name,
9423                                               r->in.value_name);
9424         if (W_ERROR_IS_OK(status)) {
9425                 status = winreg_printer_update_changeid(p->mem_ctx,
9426                                                         get_session_info_system(),
9427                                                         p->msg_ctx,
9428                                                         printer);
9429         }
9430
9431         return status;
9432 }
9433
9434 /****************************************************************
9435  _spoolss_EnumPrinterKey
9436 ****************************************************************/
9437
9438 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9439                                struct spoolss_EnumPrinterKey *r)
9440 {
9441         uint32_t        num_keys;
9442         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9443         int             snum = 0;
9444         WERROR          result = WERR_BADFILE;
9445         const char **array = NULL;
9446         DATA_BLOB blob;
9447
9448         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9449
9450         if (!Printer) {
9451                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9452                         OUR_HANDLE(r->in.handle)));
9453                 return WERR_BADFID;
9454         }
9455
9456         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9457                 return WERR_BADFID;
9458         }
9459
9460         result = winreg_enum_printer_key(p->mem_ctx,
9461                                          get_session_info_system(),
9462                                          p->msg_ctx,
9463                                          lp_const_servicename(snum),
9464                                          r->in.key_name,
9465                                          &num_keys,
9466                                          &array);
9467         if (!W_ERROR_IS_OK(result)) {
9468                 goto done;
9469         }
9470
9471         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9472                 result = WERR_NOMEM;
9473                 goto done;
9474         }
9475
9476         *r->out._ndr_size = r->in.offered / 2;
9477         *r->out.needed = blob.length;
9478
9479         if (r->in.offered < *r->out.needed) {
9480                 result = WERR_MORE_DATA;
9481         } else {
9482                 result = WERR_OK;
9483                 r->out.key_buffer->string_array = array;
9484         }
9485
9486  done:
9487         if (!W_ERROR_IS_OK(result)) {
9488                 TALLOC_FREE(array);
9489                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9490                         *r->out.needed = 0;
9491                 }
9492         }
9493
9494         return result;
9495 }
9496
9497 /****************************************************************
9498  _spoolss_DeletePrinterKey
9499 ****************************************************************/
9500
9501 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9502                                  struct spoolss_DeletePrinterKey *r)
9503 {
9504         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9505         int                     snum=0;
9506         WERROR                  status;
9507         const char *printer;
9508
9509         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9510
9511         if (!Printer) {
9512                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9513                         OUR_HANDLE(r->in.handle)));
9514                 return WERR_BADFID;
9515         }
9516
9517         /* if keyname == NULL, return error */
9518         if ( !r->in.key_name )
9519                 return WERR_INVALID_PARAM;
9520
9521         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9522                 return WERR_BADFID;
9523         }
9524
9525         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9526                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9527                         "printer properties change denied by handle\n"));
9528                 return WERR_ACCESS_DENIED;
9529         }
9530
9531         printer = lp_const_servicename(snum);
9532
9533         /* delete the key and all subkeys */
9534         status = winreg_delete_printer_key(p->mem_ctx,
9535                                            get_session_info_system(),
9536                                            p->msg_ctx,
9537                                            printer,
9538                                            r->in.key_name);
9539         if (W_ERROR_IS_OK(status)) {
9540                 status = winreg_printer_update_changeid(p->mem_ctx,
9541                                                         get_session_info_system(),
9542                                                         p->msg_ctx,
9543                                                         printer);
9544         }
9545
9546         return status;
9547 }
9548
9549 /****************************************************************
9550  _spoolss_EnumPrinterDataEx
9551 ****************************************************************/
9552
9553 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9554                                   struct spoolss_EnumPrinterDataEx *r)
9555 {
9556         uint32_t        count = 0;
9557         struct spoolss_PrinterEnumValues *info = NULL;
9558         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9559         int             snum;
9560         WERROR          result;
9561
9562         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9563
9564         *r->out.count = 0;
9565         *r->out.needed = 0;
9566         *r->out.info = NULL;
9567
9568         if (!Printer) {
9569                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9570                         OUR_HANDLE(r->in.handle)));
9571                 return WERR_BADFID;
9572         }
9573
9574         /*
9575          * first check for a keyname of NULL or "".  Win2k seems to send
9576          * this a lot and we should send back WERR_INVALID_PARAM
9577          * no need to spend time looking up the printer in this case.
9578          * --jerry
9579          */
9580
9581         if (!strlen(r->in.key_name)) {
9582                 result = WERR_INVALID_PARAM;
9583                 goto done;
9584         }
9585
9586         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9587                 return WERR_BADFID;
9588         }
9589
9590         /* now look for a match on the key name */
9591         result = winreg_enum_printer_dataex(p->mem_ctx,
9592                                             get_session_info_system(),
9593                                             p->msg_ctx,
9594                                             lp_const_servicename(snum),
9595                                             r->in.key_name,
9596                                             &count,
9597                                             &info);
9598         if (!W_ERROR_IS_OK(result)) {
9599                 goto done;
9600         }
9601
9602 #if 0 /* FIXME - gd */
9603         /* housekeeping information in the reply */
9604
9605         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9606          * the hand marshalled container size is a multiple
9607          * of 4 bytes for RPC alignment.
9608          */
9609
9610         if (needed % 4) {
9611                 needed += 4-(needed % 4);
9612         }
9613 #endif
9614         *r->out.count   = count;
9615         *r->out.info    = info;
9616
9617  done:
9618         if (!W_ERROR_IS_OK(result)) {
9619                 return result;
9620         }
9621
9622         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9623                                                spoolss_EnumPrinterDataEx,
9624                                                *r->out.info,
9625                                                *r->out.count);
9626         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9627         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9628
9629         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9630 }
9631
9632 /****************************************************************************
9633 ****************************************************************************/
9634
9635 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9636                                                  const char *servername,
9637                                                  const char *environment,
9638                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9639 {
9640         WERROR werr;
9641         char *path = NULL;
9642
9643         werr = compose_spoolss_server_path(mem_ctx,
9644                                            servername,
9645                                            environment,
9646                                            SPOOLSS_PRTPROCS_PATH,
9647                                            &path);
9648         if (!W_ERROR_IS_OK(werr)) {
9649                 return werr;
9650         }
9651
9652         DEBUG(4,("print processor directory: [%s]\n", path));
9653
9654         r->directory_name = path;
9655
9656         return WERR_OK;
9657 }
9658
9659 /****************************************************************
9660  _spoolss_GetPrintProcessorDirectory
9661 ****************************************************************/
9662
9663 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9664                                            struct spoolss_GetPrintProcessorDirectory *r)
9665 {
9666         WERROR result;
9667         char *prnproc_share = NULL;
9668         bool prnproc_share_exists = false;
9669         int snum;
9670
9671         /* that's an [in out] buffer */
9672
9673         if (!r->in.buffer && (r->in.offered != 0)) {
9674                 return WERR_INVALID_PARAM;
9675         }
9676
9677         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9678                 r->in.level));
9679
9680         *r->out.needed = 0;
9681
9682         /* r->in.level is ignored */
9683
9684         /* We always should reply with a local print processor directory so that
9685          * users are not forced to have a [prnproc$] share on the Samba spoolss
9686          * server, if users decide to do so, lets announce it though - Guenther */
9687
9688         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9689         if (!prnproc_share) {
9690                 return WERR_NOMEM;
9691         }
9692         if (snum != -1) {
9693                 prnproc_share_exists = true;
9694         }
9695
9696         result = getprintprocessordirectory_level_1(p->mem_ctx,
9697                                                     prnproc_share_exists ? r->in.server : NULL,
9698                                                     r->in.environment,
9699                                                     &r->out.info->info1);
9700         if (!W_ERROR_IS_OK(result)) {
9701                 TALLOC_FREE(r->out.info);
9702                 return result;
9703         }
9704
9705         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9706                                                                                    r->out.info, r->in.level);
9707         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9708
9709         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9710 }
9711
9712 /*******************************************************************
9713  ********************************************************************/
9714
9715 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9716                                const char *dllname)
9717 {
9718         enum ndr_err_code ndr_err;
9719         struct spoolss_MonitorUi ui;
9720
9721         ui.dll_name = dllname;
9722
9723         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9724                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9725         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9726                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9727         }
9728         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9729 }
9730
9731 /*******************************************************************
9732  Streams the monitor UI DLL name in UNICODE
9733 *******************************************************************/
9734
9735 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9736                                struct security_token *token, DATA_BLOB *in,
9737                                DATA_BLOB *out, uint32_t *needed)
9738 {
9739         const char *dllname = "tcpmonui.dll";
9740
9741         *needed = (strlen(dllname)+1) * 2;
9742
9743         if (out->length < *needed) {
9744                 return WERR_INSUFFICIENT_BUFFER;
9745         }
9746
9747         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9748                 return WERR_NOMEM;
9749         }
9750
9751         return WERR_OK;
9752 }
9753
9754 /*******************************************************************
9755  ********************************************************************/
9756
9757 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9758                              struct spoolss_PortData1 *port1,
9759                              const DATA_BLOB *buf)
9760 {
9761         enum ndr_err_code ndr_err;
9762         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9763                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9764         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9765                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9766         }
9767         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9768 }
9769
9770 /*******************************************************************
9771  ********************************************************************/
9772
9773 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9774                              struct spoolss_PortData2 *port2,
9775                              const DATA_BLOB *buf)
9776 {
9777         enum ndr_err_code ndr_err;
9778         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9779                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9780         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9781                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9782         }
9783         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9784 }
9785
9786 /*******************************************************************
9787  Create a new TCP/IP port
9788 *******************************************************************/
9789
9790 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9791                              struct security_token *token, DATA_BLOB *in,
9792                              DATA_BLOB *out, uint32_t *needed)
9793 {
9794         struct spoolss_PortData1 port1;
9795         struct spoolss_PortData2 port2;
9796         char *device_uri = NULL;
9797         uint32_t version;
9798
9799         const char *portname;
9800         const char *hostaddress;
9801         const char *queue;
9802         uint32_t port_number;
9803         uint32_t protocol;
9804
9805         /* peek for spoolss_PortData version */
9806
9807         if (!in || (in->length < (128 + 4))) {
9808                 return WERR_GENERAL_FAILURE;
9809         }
9810
9811         version = IVAL(in->data, 128);
9812
9813         switch (version) {
9814                 case 1:
9815                         ZERO_STRUCT(port1);
9816
9817                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9818                                 return WERR_NOMEM;
9819                         }
9820
9821                         portname        = port1.portname;
9822                         hostaddress     = port1.hostaddress;
9823                         queue           = port1.queue;
9824                         protocol        = port1.protocol;
9825                         port_number     = port1.port_number;
9826
9827                         break;
9828                 case 2:
9829                         ZERO_STRUCT(port2);
9830
9831                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9832                                 return WERR_NOMEM;
9833                         }
9834
9835                         portname        = port2.portname;
9836                         hostaddress     = port2.hostaddress;
9837                         queue           = port2.queue;
9838                         protocol        = port2.protocol;
9839                         port_number     = port2.port_number;
9840
9841                         break;
9842                 default:
9843                         DEBUG(1,("xcvtcp_addport: "
9844                                 "unknown version of port_data: %d\n", version));
9845                         return WERR_UNKNOWN_PORT;
9846         }
9847
9848         /* create the device URI and call the add_port_hook() */
9849
9850         switch (protocol) {
9851         case PROTOCOL_RAWTCP_TYPE:
9852                 device_uri = talloc_asprintf(mem_ctx,
9853                                 "socket://%s:%d/", hostaddress,
9854                                 port_number);
9855                 break;
9856
9857         case PROTOCOL_LPR_TYPE:
9858                 device_uri = talloc_asprintf(mem_ctx,
9859                         "lpr://%s/%s", hostaddress, queue );
9860                 break;
9861
9862         default:
9863                 return WERR_UNKNOWN_PORT;
9864         }
9865
9866         if (!device_uri) {
9867                 return WERR_NOMEM;
9868         }
9869
9870         return add_port_hook(mem_ctx, token, portname, device_uri);
9871 }
9872
9873 /*******************************************************************
9874 *******************************************************************/
9875
9876 struct xcv_api_table xcvtcp_cmds[] = {
9877         { "MonitorUI",  xcvtcp_monitorui },
9878         { "AddPort",    xcvtcp_addport},
9879         { NULL,         NULL }
9880 };
9881
9882 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9883                                      struct security_token *token, const char *command,
9884                                      DATA_BLOB *inbuf,
9885                                      DATA_BLOB *outbuf,
9886                                      uint32_t *needed )
9887 {
9888         int i;
9889
9890         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9891
9892         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9893                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9894                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9895         }
9896
9897         return WERR_BADFUNC;
9898 }
9899
9900 /*******************************************************************
9901 *******************************************************************/
9902 #if 0   /* don't support management using the "Local Port" monitor */
9903
9904 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9905                                  struct security_token *token, DATA_BLOB *in,
9906                                  DATA_BLOB *out, uint32_t *needed)
9907 {
9908         const char *dllname = "localui.dll";
9909
9910         *needed = (strlen(dllname)+1) * 2;
9911
9912         if (out->length < *needed) {
9913                 return WERR_INSUFFICIENT_BUFFER;
9914         }
9915
9916         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9917                 return WERR_NOMEM;
9918         }
9919
9920         return WERR_OK;
9921 }
9922
9923 /*******************************************************************
9924 *******************************************************************/
9925
9926 struct xcv_api_table xcvlocal_cmds[] = {
9927         { "MonitorUI",  xcvlocal_monitorui },
9928         { NULL,         NULL }
9929 };
9930 #else
9931 struct xcv_api_table xcvlocal_cmds[] = {
9932         { NULL,         NULL }
9933 };
9934 #endif
9935
9936
9937
9938 /*******************************************************************
9939 *******************************************************************/
9940
9941 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9942                                        struct security_token *token, const char *command,
9943                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9944                                        uint32_t *needed)
9945 {
9946         int i;
9947
9948         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9949
9950         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9951                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9952                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9953         }
9954         return WERR_BADFUNC;
9955 }
9956
9957 /****************************************************************
9958  _spoolss_XcvData
9959 ****************************************************************/
9960
9961 WERROR _spoolss_XcvData(struct pipes_struct *p,
9962                         struct spoolss_XcvData *r)
9963 {
9964         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9965         DATA_BLOB out_data = data_blob_null;
9966         WERROR werror;
9967
9968         if (!Printer) {
9969                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9970                         OUR_HANDLE(r->in.handle)));
9971                 return WERR_BADFID;
9972         }
9973
9974         /* Has to be a handle to the TCP/IP port monitor */
9975
9976         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9977                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9978                 return WERR_BADFID;
9979         }
9980
9981         /* requires administrative access to the server */
9982
9983         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9984                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9985                 return WERR_ACCESS_DENIED;
9986         }
9987
9988         /* Allocate the outgoing buffer */
9989
9990         if (r->in.out_data_size) {
9991                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9992                 if (out_data.data == NULL) {
9993                         return WERR_NOMEM;
9994                 }
9995         }
9996
9997         switch ( Printer->printer_type ) {
9998         case SPLHND_PORTMON_TCP:
9999                 werror = process_xcvtcp_command(p->mem_ctx,
10000                                                 p->session_info->security_token,
10001                                                 r->in.function_name,
10002                                                 &r->in.in_data, &out_data,
10003                                                 r->out.needed);
10004                 break;
10005         case SPLHND_PORTMON_LOCAL:
10006                 werror = process_xcvlocal_command(p->mem_ctx,
10007                                                   p->session_info->security_token,
10008                                                   r->in.function_name,
10009                                                   &r->in.in_data, &out_data,
10010                                                   r->out.needed);
10011                 break;
10012         default:
10013                 werror = WERR_INVALID_PRINT_MONITOR;
10014         }
10015
10016         if (!W_ERROR_IS_OK(werror)) {
10017                 return werror;
10018         }
10019
10020         *r->out.status_code = 0;
10021
10022         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10023                 memcpy(r->out.out_data, out_data.data,
10024                         MIN(r->in.out_data_size, out_data.length));
10025         }
10026
10027         return WERR_OK;
10028 }
10029
10030 /****************************************************************
10031  _spoolss_AddPrintProcessor
10032 ****************************************************************/
10033
10034 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10035                                   struct spoolss_AddPrintProcessor *r)
10036 {
10037         /* for now, just indicate success and ignore the add.  We'll
10038            automatically set the winprint processor for printer
10039            entries later.  Used to debug the LexMark Optra S 1855 PCL
10040            driver --jerry */
10041
10042         return WERR_OK;
10043 }
10044
10045 /****************************************************************
10046  _spoolss_AddPort
10047 ****************************************************************/
10048
10049 WERROR _spoolss_AddPort(struct pipes_struct *p,
10050                         struct spoolss_AddPort *r)
10051 {
10052         /* do what w2k3 does */
10053
10054         return WERR_NOT_SUPPORTED;
10055 }
10056
10057 /****************************************************************
10058  _spoolss_GetPrinterDriver
10059 ****************************************************************/
10060
10061 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10062                                  struct spoolss_GetPrinterDriver *r)
10063 {
10064         p->rng_fault_state = true;
10065         return WERR_NOT_SUPPORTED;
10066 }
10067
10068 /****************************************************************
10069  _spoolss_ReadPrinter
10070 ****************************************************************/
10071
10072 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10073                             struct spoolss_ReadPrinter *r)
10074 {
10075         p->rng_fault_state = true;
10076         return WERR_NOT_SUPPORTED;
10077 }
10078
10079 /****************************************************************
10080  _spoolss_WaitForPrinterChange
10081 ****************************************************************/
10082
10083 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10084                                      struct spoolss_WaitForPrinterChange *r)
10085 {
10086         p->rng_fault_state = true;
10087         return WERR_NOT_SUPPORTED;
10088 }
10089
10090 /****************************************************************
10091  _spoolss_ConfigurePort
10092 ****************************************************************/
10093
10094 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10095                               struct spoolss_ConfigurePort *r)
10096 {
10097         p->rng_fault_state = true;
10098         return WERR_NOT_SUPPORTED;
10099 }
10100
10101 /****************************************************************
10102  _spoolss_DeletePort
10103 ****************************************************************/
10104
10105 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10106                            struct spoolss_DeletePort *r)
10107 {
10108         p->rng_fault_state = true;
10109         return WERR_NOT_SUPPORTED;
10110 }
10111
10112 /****************************************************************
10113  _spoolss_CreatePrinterIC
10114 ****************************************************************/
10115
10116 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10117                                 struct spoolss_CreatePrinterIC *r)
10118 {
10119         p->rng_fault_state = true;
10120         return WERR_NOT_SUPPORTED;
10121 }
10122
10123 /****************************************************************
10124  _spoolss_PlayGDIScriptOnPrinterIC
10125 ****************************************************************/
10126
10127 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10128                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10129 {
10130         p->rng_fault_state = true;
10131         return WERR_NOT_SUPPORTED;
10132 }
10133
10134 /****************************************************************
10135  _spoolss_DeletePrinterIC
10136 ****************************************************************/
10137
10138 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10139                                 struct spoolss_DeletePrinterIC *r)
10140 {
10141         p->rng_fault_state = true;
10142         return WERR_NOT_SUPPORTED;
10143 }
10144
10145 /****************************************************************
10146  _spoolss_AddPrinterConnection
10147 ****************************************************************/
10148
10149 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10150                                      struct spoolss_AddPrinterConnection *r)
10151 {
10152         p->rng_fault_state = true;
10153         return WERR_NOT_SUPPORTED;
10154 }
10155
10156 /****************************************************************
10157  _spoolss_DeletePrinterConnection
10158 ****************************************************************/
10159
10160 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10161                                         struct spoolss_DeletePrinterConnection *r)
10162 {
10163         p->rng_fault_state = true;
10164         return WERR_NOT_SUPPORTED;
10165 }
10166
10167 /****************************************************************
10168  _spoolss_PrinterMessageBox
10169 ****************************************************************/
10170
10171 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10172                                   struct spoolss_PrinterMessageBox *r)
10173 {
10174         p->rng_fault_state = true;
10175         return WERR_NOT_SUPPORTED;
10176 }
10177
10178 /****************************************************************
10179  _spoolss_AddMonitor
10180 ****************************************************************/
10181
10182 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10183                            struct spoolss_AddMonitor *r)
10184 {
10185         p->rng_fault_state = true;
10186         return WERR_NOT_SUPPORTED;
10187 }
10188
10189 /****************************************************************
10190  _spoolss_DeleteMonitor
10191 ****************************************************************/
10192
10193 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10194                               struct spoolss_DeleteMonitor *r)
10195 {
10196         p->rng_fault_state = true;
10197         return WERR_NOT_SUPPORTED;
10198 }
10199
10200 /****************************************************************
10201  _spoolss_DeletePrintProcessor
10202 ****************************************************************/
10203
10204 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10205                                      struct spoolss_DeletePrintProcessor *r)
10206 {
10207         p->rng_fault_state = true;
10208         return WERR_NOT_SUPPORTED;
10209 }
10210
10211 /****************************************************************
10212  _spoolss_AddPrintProvidor
10213 ****************************************************************/
10214
10215 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10216                                  struct spoolss_AddPrintProvidor *r)
10217 {
10218         p->rng_fault_state = true;
10219         return WERR_NOT_SUPPORTED;
10220 }
10221
10222 /****************************************************************
10223  _spoolss_DeletePrintProvidor
10224 ****************************************************************/
10225
10226 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10227                                     struct spoolss_DeletePrintProvidor *r)
10228 {
10229         p->rng_fault_state = true;
10230         return WERR_NOT_SUPPORTED;
10231 }
10232
10233 /****************************************************************
10234  _spoolss_FindFirstPrinterChangeNotification
10235 ****************************************************************/
10236
10237 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10238                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10239 {
10240         p->rng_fault_state = true;
10241         return WERR_NOT_SUPPORTED;
10242 }
10243
10244 /****************************************************************
10245  _spoolss_FindNextPrinterChangeNotification
10246 ****************************************************************/
10247
10248 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10249                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10250 {
10251         p->rng_fault_state = true;
10252         return WERR_NOT_SUPPORTED;
10253 }
10254
10255 /****************************************************************
10256  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10257 ****************************************************************/
10258
10259 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10260                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10261 {
10262         p->rng_fault_state = true;
10263         return WERR_NOT_SUPPORTED;
10264 }
10265
10266 /****************************************************************
10267  _spoolss_ReplyOpenPrinter
10268 ****************************************************************/
10269
10270 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10271                                  struct spoolss_ReplyOpenPrinter *r)
10272 {
10273         p->rng_fault_state = true;
10274         return WERR_NOT_SUPPORTED;
10275 }
10276
10277 /****************************************************************
10278  _spoolss_RouterReplyPrinter
10279 ****************************************************************/
10280
10281 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10282                                    struct spoolss_RouterReplyPrinter *r)
10283 {
10284         p->rng_fault_state = true;
10285         return WERR_NOT_SUPPORTED;
10286 }
10287
10288 /****************************************************************
10289  _spoolss_ReplyClosePrinter
10290 ****************************************************************/
10291
10292 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10293                                   struct spoolss_ReplyClosePrinter *r)
10294 {
10295         p->rng_fault_state = true;
10296         return WERR_NOT_SUPPORTED;
10297 }
10298
10299 /****************************************************************
10300  _spoolss_AddPortEx
10301 ****************************************************************/
10302
10303 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10304                           struct spoolss_AddPortEx *r)
10305 {
10306         p->rng_fault_state = true;
10307         return WERR_NOT_SUPPORTED;
10308 }
10309
10310 /****************************************************************
10311  _spoolss_RouterFindFirstPrinterChangeNotification
10312 ****************************************************************/
10313
10314 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10315                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10316 {
10317         p->rng_fault_state = true;
10318         return WERR_NOT_SUPPORTED;
10319 }
10320
10321 /****************************************************************
10322  _spoolss_SpoolerInit
10323 ****************************************************************/
10324
10325 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10326                             struct spoolss_SpoolerInit *r)
10327 {
10328         p->rng_fault_state = true;
10329         return WERR_NOT_SUPPORTED;
10330 }
10331
10332 /****************************************************************
10333  _spoolss_ResetPrinterEx
10334 ****************************************************************/
10335
10336 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10337                                struct spoolss_ResetPrinterEx *r)
10338 {
10339         p->rng_fault_state = true;
10340         return WERR_NOT_SUPPORTED;
10341 }
10342
10343 /****************************************************************
10344  _spoolss_RouterReplyPrinterEx
10345 ****************************************************************/
10346
10347 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10348                                      struct spoolss_RouterReplyPrinterEx *r)
10349 {
10350         p->rng_fault_state = true;
10351         return WERR_NOT_SUPPORTED;
10352 }
10353
10354 /****************************************************************
10355  _spoolss_44
10356 ****************************************************************/
10357
10358 WERROR _spoolss_44(struct pipes_struct *p,
10359                    struct spoolss_44 *r)
10360 {
10361         p->rng_fault_state = true;
10362         return WERR_NOT_SUPPORTED;
10363 }
10364
10365 /****************************************************************
10366  _spoolss_SetPort
10367 ****************************************************************/
10368
10369 WERROR _spoolss_SetPort(struct pipes_struct *p,
10370                         struct spoolss_SetPort *r)
10371 {
10372         p->rng_fault_state = true;
10373         return WERR_NOT_SUPPORTED;
10374 }
10375
10376 /****************************************************************
10377  _spoolss_4a
10378 ****************************************************************/
10379
10380 WERROR _spoolss_4a(struct pipes_struct *p,
10381                    struct spoolss_4a *r)
10382 {
10383         p->rng_fault_state = true;
10384         return WERR_NOT_SUPPORTED;
10385 }
10386
10387 /****************************************************************
10388  _spoolss_4b
10389 ****************************************************************/
10390
10391 WERROR _spoolss_4b(struct pipes_struct *p,
10392                    struct spoolss_4b *r)
10393 {
10394         p->rng_fault_state = true;
10395         return WERR_NOT_SUPPORTED;
10396 }
10397
10398 /****************************************************************
10399  _spoolss_4c
10400 ****************************************************************/
10401
10402 WERROR _spoolss_4c(struct pipes_struct *p,
10403                    struct spoolss_4c *r)
10404 {
10405         p->rng_fault_state = true;
10406         return WERR_NOT_SUPPORTED;
10407 }
10408
10409 /****************************************************************
10410  _spoolss_53
10411 ****************************************************************/
10412
10413 WERROR _spoolss_53(struct pipes_struct *p,
10414                    struct spoolss_53 *r)
10415 {
10416         p->rng_fault_state = true;
10417         return WERR_NOT_SUPPORTED;
10418 }
10419
10420 /****************************************************************
10421  _spoolss_AddPerMachineConnection
10422 ****************************************************************/
10423
10424 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10425                                         struct spoolss_AddPerMachineConnection *r)
10426 {
10427         p->rng_fault_state = true;
10428         return WERR_NOT_SUPPORTED;
10429 }
10430
10431 /****************************************************************
10432  _spoolss_DeletePerMachineConnection
10433 ****************************************************************/
10434
10435 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10436                                            struct spoolss_DeletePerMachineConnection *r)
10437 {
10438         p->rng_fault_state = true;
10439         return WERR_NOT_SUPPORTED;
10440 }
10441
10442 /****************************************************************
10443  _spoolss_EnumPerMachineConnections
10444 ****************************************************************/
10445
10446 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10447                                           struct spoolss_EnumPerMachineConnections *r)
10448 {
10449         p->rng_fault_state = true;
10450         return WERR_NOT_SUPPORTED;
10451 }
10452
10453 /****************************************************************
10454  _spoolss_5a
10455 ****************************************************************/
10456
10457 WERROR _spoolss_5a(struct pipes_struct *p,
10458                    struct spoolss_5a *r)
10459 {
10460         p->rng_fault_state = true;
10461         return WERR_NOT_SUPPORTED;
10462 }
10463
10464 /****************************************************************
10465  _spoolss_5b
10466 ****************************************************************/
10467
10468 WERROR _spoolss_5b(struct pipes_struct *p,
10469                    struct spoolss_5b *r)
10470 {
10471         p->rng_fault_state = true;
10472         return WERR_NOT_SUPPORTED;
10473 }
10474
10475 /****************************************************************
10476  _spoolss_5c
10477 ****************************************************************/
10478
10479 WERROR _spoolss_5c(struct pipes_struct *p,
10480                    struct spoolss_5c *r)
10481 {
10482         p->rng_fault_state = true;
10483         return WERR_NOT_SUPPORTED;
10484 }
10485
10486 /****************************************************************
10487  _spoolss_5d
10488 ****************************************************************/
10489
10490 WERROR _spoolss_5d(struct pipes_struct *p,
10491                    struct spoolss_5d *r)
10492 {
10493         p->rng_fault_state = true;
10494         return WERR_NOT_SUPPORTED;
10495 }
10496
10497 /****************************************************************
10498  _spoolss_5e
10499 ****************************************************************/
10500
10501 WERROR _spoolss_5e(struct pipes_struct *p,
10502                    struct spoolss_5e *r)
10503 {
10504         p->rng_fault_state = true;
10505         return WERR_NOT_SUPPORTED;
10506 }
10507
10508 /****************************************************************
10509  _spoolss_5f
10510 ****************************************************************/
10511
10512 WERROR _spoolss_5f(struct pipes_struct *p,
10513                    struct spoolss_5f *r)
10514 {
10515         p->rng_fault_state = true;
10516         return WERR_NOT_SUPPORTED;
10517 }
10518
10519 /****************************************************************
10520  _spoolss_60
10521 ****************************************************************/
10522
10523 WERROR _spoolss_60(struct pipes_struct *p,
10524                    struct spoolss_60 *r)
10525 {
10526         p->rng_fault_state = true;
10527         return WERR_NOT_SUPPORTED;
10528 }
10529
10530 /****************************************************************
10531  _spoolss_61
10532 ****************************************************************/
10533
10534 WERROR _spoolss_61(struct pipes_struct *p,
10535                    struct spoolss_61 *r)
10536 {
10537         p->rng_fault_state = true;
10538         return WERR_NOT_SUPPORTED;
10539 }
10540
10541 /****************************************************************
10542  _spoolss_62
10543 ****************************************************************/
10544
10545 WERROR _spoolss_62(struct pipes_struct *p,
10546                    struct spoolss_62 *r)
10547 {
10548         p->rng_fault_state = true;
10549         return WERR_NOT_SUPPORTED;
10550 }
10551
10552 /****************************************************************
10553  _spoolss_63
10554 ****************************************************************/
10555
10556 WERROR _spoolss_63(struct pipes_struct *p,
10557                    struct spoolss_63 *r)
10558 {
10559         p->rng_fault_state = true;
10560         return WERR_NOT_SUPPORTED;
10561 }
10562
10563 /****************************************************************
10564  _spoolss_64
10565 ****************************************************************/
10566
10567 WERROR _spoolss_64(struct pipes_struct *p,
10568                    struct spoolss_64 *r)
10569 {
10570         p->rng_fault_state = true;
10571         return WERR_NOT_SUPPORTED;
10572 }
10573
10574 /****************************************************************
10575  _spoolss_65
10576 ****************************************************************/
10577
10578 WERROR _spoolss_65(struct pipes_struct *p,
10579                    struct spoolss_65 *r)
10580 {
10581         p->rng_fault_state = true;
10582         return WERR_NOT_SUPPORTED;
10583 }
10584
10585 /****************************************************************
10586  _spoolss_GetCorePrinterDrivers
10587 ****************************************************************/
10588
10589 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10590                                       struct spoolss_GetCorePrinterDrivers *r)
10591 {
10592         p->rng_fault_state = true;
10593         return WERR_NOT_SUPPORTED;
10594 }
10595
10596 /****************************************************************
10597  _spoolss_67
10598 ****************************************************************/
10599
10600 WERROR _spoolss_67(struct pipes_struct *p,
10601                    struct spoolss_67 *r)
10602 {
10603         p->rng_fault_state = true;
10604         return WERR_NOT_SUPPORTED;
10605 }
10606
10607 /****************************************************************
10608  _spoolss_GetPrinterDriverPackagePath
10609 ****************************************************************/
10610
10611 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10612                                             struct spoolss_GetPrinterDriverPackagePath *r)
10613 {
10614         p->rng_fault_state = true;
10615         return WERR_NOT_SUPPORTED;
10616 }
10617
10618 /****************************************************************
10619  _spoolss_69
10620 ****************************************************************/
10621
10622 WERROR _spoolss_69(struct pipes_struct *p,
10623                    struct spoolss_69 *r)
10624 {
10625         p->rng_fault_state = true;
10626         return WERR_NOT_SUPPORTED;
10627 }
10628
10629 /****************************************************************
10630  _spoolss_6a
10631 ****************************************************************/
10632
10633 WERROR _spoolss_6a(struct pipes_struct *p,
10634                    struct spoolss_6a *r)
10635 {
10636         p->rng_fault_state = true;
10637         return WERR_NOT_SUPPORTED;
10638 }
10639
10640 /****************************************************************
10641  _spoolss_6b
10642 ****************************************************************/
10643
10644 WERROR _spoolss_6b(struct pipes_struct *p,
10645                    struct spoolss_6b *r)
10646 {
10647         p->rng_fault_state = true;
10648         return WERR_NOT_SUPPORTED;
10649 }
10650
10651 /****************************************************************
10652  _spoolss_6c
10653 ****************************************************************/
10654
10655 WERROR _spoolss_6c(struct pipes_struct *p,
10656                    struct spoolss_6c *r)
10657 {
10658         p->rng_fault_state = true;
10659         return WERR_NOT_SUPPORTED;
10660 }
10661
10662 /****************************************************************
10663  _spoolss_6d
10664 ****************************************************************/
10665
10666 WERROR _spoolss_6d(struct pipes_struct *p,
10667                    struct spoolss_6d *r)
10668 {
10669         p->rng_fault_state = true;
10670         return WERR_NOT_SUPPORTED;
10671 }