s3-messages: make ndr_messaging.h part of messages.h.
[ab/samba.git/.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "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 "../libcli/security/security.h"
38 #include "librpc/gen_ndr/ndr_security.h"
39 #include "registry.h"
40 #include "registry/reg_objects.h"
41 #include "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "auth.h"
50 #include "messages.h"
51
52 /* macros stolen from s4 spoolss server */
53 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
54         ((info)?ndr_size_##fn(info, level, 0):0)
55
56 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
57         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
58
59 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
60         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
61
62 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
63
64 #undef DBGC_CLASS
65 #define DBGC_CLASS DBGC_RPC_SRV
66
67 #ifndef MAX_OPEN_PRINTER_EXS
68 #define MAX_OPEN_PRINTER_EXS 50
69 #endif
70
71 struct notify_back_channel;
72
73 /* structure to store the printer handles */
74 /* and a reference to what it's pointing to */
75 /* and the notify info asked about */
76 /* that's the central struct */
77 struct printer_handle {
78         struct printer_handle *prev, *next;
79         bool document_started;
80         bool page_started;
81         uint32 jobid; /* jobid in printing backend */
82         int printer_type;
83         const char *servername;
84         fstring sharename;
85         uint32 type;
86         uint32 access_granted;
87         struct {
88                 uint32 flags;
89                 uint32 options;
90                 fstring localmachine;
91                 uint32 printerlocal;
92                 struct spoolss_NotifyOption *option;
93                 struct policy_handle cli_hnd;
94                 struct notify_back_channel *cli_chan;
95                 uint32 change;
96                 /* are we in a FindNextPrinterChangeNotify() call? */
97                 bool fnpcn;
98                 struct messaging_context *msg_ctx;
99         } notify;
100         struct {
101                 fstring machine;
102                 fstring user;
103         } client;
104
105         /* devmode sent in the OpenPrinter() call */
106         struct spoolss_DeviceMode *devmode;
107
108         /* TODO cache the printer info2 structure */
109         struct spoolss_PrinterInfo2 *info2;
110
111 };
112
113 static struct printer_handle *printers_list;
114
115 struct printer_session_counter {
116         struct printer_session_counter *next;
117         struct printer_session_counter *prev;
118
119         int snum;
120         uint32_t counter;
121 };
122
123 static struct printer_session_counter *counter_list;
124
125 struct notify_back_channel {
126         struct notify_back_channel *prev, *next;
127
128         /* associated client */
129         struct sockaddr_storage client_address;
130
131         /* print notify back-channel pipe handle*/
132         struct rpc_pipe_client *cli_pipe;
133         struct dcerpc_binding_handle *binding_handle;
134         uint32_t active_connections;
135 };
136
137 static struct notify_back_channel *back_channels;
138
139 /* Map generic permissions to printer object specific permissions */
140
141 const struct standard_mapping printer_std_mapping = {
142         PRINTER_READ,
143         PRINTER_WRITE,
144         PRINTER_EXECUTE,
145         PRINTER_ALL_ACCESS
146 };
147
148 /* Map generic permissions to print server object specific permissions */
149
150 const struct standard_mapping printserver_std_mapping = {
151         SERVER_READ,
152         SERVER_WRITE,
153         SERVER_EXECUTE,
154         SERVER_ALL_ACCESS
155 };
156
157 /* API table for Xcv Monitor functions */
158
159 struct xcv_api_table {
160         const char *name;
161         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
162 };
163
164 static void prune_printername_cache(void);
165
166 /********************************************************************
167  * Canonicalize servername.
168  ********************************************************************/
169
170 static const char *canon_servername(const char *servername)
171 {
172         const char *pservername = servername;
173         while (*pservername == '\\') {
174                 pservername++;
175         }
176         return pservername;
177 }
178
179 /* translate between internal status numbers and NT status numbers */
180 static int nt_printj_status(int v)
181 {
182         switch (v) {
183         case LPQ_QUEUED:
184                 return 0;
185         case LPQ_PAUSED:
186                 return JOB_STATUS_PAUSED;
187         case LPQ_SPOOLING:
188                 return JOB_STATUS_SPOOLING;
189         case LPQ_PRINTING:
190                 return JOB_STATUS_PRINTING;
191         case LPQ_ERROR:
192                 return JOB_STATUS_ERROR;
193         case LPQ_DELETING:
194                 return JOB_STATUS_DELETING;
195         case LPQ_OFFLINE:
196                 return JOB_STATUS_OFFLINE;
197         case LPQ_PAPEROUT:
198                 return JOB_STATUS_PAPEROUT;
199         case LPQ_PRINTED:
200                 return JOB_STATUS_PRINTED;
201         case LPQ_DELETED:
202                 return JOB_STATUS_DELETED;
203         case LPQ_BLOCKED:
204                 return JOB_STATUS_BLOCKED_DEVQ;
205         case LPQ_USER_INTERVENTION:
206                 return JOB_STATUS_USER_INTERVENTION;
207         }
208         return 0;
209 }
210
211 static int nt_printq_status(int v)
212 {
213         switch (v) {
214         case LPQ_PAUSED:
215                 return PRINTER_STATUS_PAUSED;
216         case LPQ_QUEUED:
217         case LPQ_SPOOLING:
218         case LPQ_PRINTING:
219                 return 0;
220         }
221         return 0;
222 }
223
224 /***************************************************************************
225  Disconnect from the client
226 ****************************************************************************/
227
228 static void srv_spoolss_replycloseprinter(int snum,
229                                           struct printer_handle *prn_hnd)
230 {
231         WERROR result;
232         NTSTATUS status;
233
234         /*
235          * Tell the specific printing tdb we no longer want messages for this printer
236          * by deregistering our PID.
237          */
238
239         if (!print_notify_deregister_pid(snum)) {
240                 DEBUG(0, ("Failed to register our pid for printer %s\n",
241                           lp_const_servicename(snum)));
242         }
243
244         /* weird if the test succeeds !!! */
245         if (prn_hnd->notify.cli_chan == NULL ||
246             prn_hnd->notify.cli_chan->active_connections == 0) {
247                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
248                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
249                 TALLOC_FREE(prn_hnd->notify.cli_chan);
250                 return;
251         }
252
253         status = dcerpc_spoolss_ReplyClosePrinter(
254                                         prn_hnd->notify.cli_chan->binding_handle,
255                                         talloc_tos(),
256                                         &prn_hnd->notify.cli_hnd,
257                                         &result);
258         if (!NT_STATUS_IS_OK(status)) {
259                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
260                           nt_errstr(status)));
261                 result = ntstatus_to_werror(status);
262         } else if (!W_ERROR_IS_OK(result)) {
263                 DEBUG(0, ("reply_close_printer failed [%s].\n",
264                           win_errstr(result)));
265         }
266
267         /* if it's the last connection, deconnect the IPC$ share */
268         if (prn_hnd->notify.cli_chan->active_connections == 1) {
269
270                 prn_hnd->notify.cli_chan->binding_handle = NULL;
271                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
272                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
273                 TALLOC_FREE(prn_hnd->notify.cli_chan);
274
275                 if (prn_hnd->notify.msg_ctx != NULL) {
276                         messaging_deregister(prn_hnd->notify.msg_ctx,
277                                              MSG_PRINTER_NOTIFY2, NULL);
278
279                         /*
280                          * Tell the serverid.tdb we're no longer
281                          * interested in printer notify messages.
282                          */
283
284                         serverid_register_msg_flags(
285                                 messaging_server_id(prn_hnd->notify.msg_ctx),
286                                 false, FLAG_MSG_PRINT_NOTIFY);
287                 }
288         }
289
290         if (prn_hnd->notify.cli_chan) {
291                 prn_hnd->notify.cli_chan->active_connections--;
292         }
293 }
294
295 /****************************************************************************
296  Functions to free a printer entry datastruct.
297 ****************************************************************************/
298
299 static int printer_entry_destructor(struct printer_handle *Printer)
300 {
301         if (Printer->notify.cli_chan != NULL &&
302             Printer->notify.cli_chan->active_connections > 0) {
303                 int snum = -1;
304
305                 switch(Printer->printer_type) {
306                 case SPLHND_SERVER:
307                         srv_spoolss_replycloseprinter(snum, Printer);
308                         break;
309
310                 case SPLHND_PRINTER:
311                         snum = print_queue_snum(Printer->sharename);
312                         if (snum != -1) {
313                                 srv_spoolss_replycloseprinter(snum, Printer);
314                         }
315                         break;
316                 default:
317                         break;
318                 }
319         }
320
321         Printer->notify.flags=0;
322         Printer->notify.options=0;
323         Printer->notify.localmachine[0]='\0';
324         Printer->notify.printerlocal=0;
325         TALLOC_FREE(Printer->notify.option);
326         TALLOC_FREE(Printer->devmode);
327
328         /* Remove from the internal list. */
329         DLIST_REMOVE(printers_list, Printer);
330         return 0;
331 }
332
333 /****************************************************************************
334   find printer index by handle
335 ****************************************************************************/
336
337 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
338                                                         struct policy_handle *hnd)
339 {
340         struct printer_handle *find_printer = NULL;
341
342         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
343                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
344                 return NULL;
345         }
346
347         return find_printer;
348 }
349
350 /****************************************************************************
351  Close printer index by handle.
352 ****************************************************************************/
353
354 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
355 {
356         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
357
358         if (!Printer) {
359                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
360                         OUR_HANDLE(hnd)));
361                 return false;
362         }
363
364         close_policy_hnd(p, hnd);
365
366         return true;
367 }
368
369 /****************************************************************************
370  Delete a printer given a handle.
371 ****************************************************************************/
372
373 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
374                                   const char *sharename,
375                                   struct messaging_context *msg_ctx)
376 {
377         char *cmd = lp_deleteprinter_cmd();
378         char *command = NULL;
379         int ret;
380         bool is_print_op = false;
381
382         /* can't fail if we don't try */
383
384         if ( !*cmd )
385                 return WERR_OK;
386
387         command = talloc_asprintf(ctx,
388                         "%s \"%s\"",
389                         cmd, sharename);
390         if (!command) {
391                 return WERR_NOMEM;
392         }
393         if ( token )
394                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
395
396         DEBUG(10,("Running [%s]\n", command));
397
398         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
399
400         if ( is_print_op )
401                 become_root();
402
403         if ( (ret = smbrun(command, NULL)) == 0 ) {
404                 /* Tell everyone we updated smb.conf. */
405                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
406         }
407
408         if ( is_print_op )
409                 unbecome_root();
410
411         /********** END SePrintOperatorPrivlege BLOCK **********/
412
413         DEBUGADD(10,("returned [%d]\n", ret));
414
415         TALLOC_FREE(command);
416
417         if (ret != 0)
418                 return WERR_BADFID; /* What to return here? */
419
420         /* go ahead and re-read the services immediately */
421         become_root();
422         reload_services(msg_ctx, -1, false);
423         unbecome_root();
424
425         if ( lp_servicenumber( sharename ) >= 0 )
426                 return WERR_ACCESS_DENIED;
427
428         return WERR_OK;
429 }
430
431 /****************************************************************************
432  Delete a printer given a handle.
433 ****************************************************************************/
434
435 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
436 {
437         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
438         WERROR result;
439
440         if (!Printer) {
441                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
442                         OUR_HANDLE(hnd)));
443                 return WERR_BADFID;
444         }
445
446         /*
447          * It turns out that Windows allows delete printer on a handle
448          * opened by an admin user, then used on a pipe handle created
449          * by an anonymous user..... but they're working on security.... riiight !
450          * JRA.
451          */
452
453         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
454                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
455                 return WERR_ACCESS_DENIED;
456         }
457
458         /* this does not need a become root since the access check has been
459            done on the handle already */
460
461         result = winreg_delete_printer_key(p->mem_ctx,
462                                            get_session_info_system(),
463                                            p->msg_ctx,
464                                            Printer->sharename,
465                                            "");
466         if (!W_ERROR_IS_OK(result)) {
467                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
468                 return WERR_BADFID;
469         }
470
471         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
472                                      Printer->sharename, p->msg_ctx);
473         if (!W_ERROR_IS_OK(result)) {
474                 return result;
475         }
476         prune_printername_cache();
477         return WERR_OK;
478 }
479
480 /****************************************************************************
481  Return the snum of a printer corresponding to an handle.
482 ****************************************************************************/
483
484 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
485                              int *number, struct share_params **params)
486 {
487         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
488
489         if (!Printer) {
490                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
491                         OUR_HANDLE(hnd)));
492                 return false;
493         }
494
495         switch (Printer->printer_type) {
496                 case SPLHND_PRINTER:
497                         DEBUG(4,("short name:%s\n", Printer->sharename));
498                         *number = print_queue_snum(Printer->sharename);
499                         return (*number != -1);
500                 case SPLHND_SERVER:
501                         return false;
502                 default:
503                         return false;
504         }
505 }
506
507 /****************************************************************************
508  Set printer handle type.
509  Check if it's \\server or \\server\printer
510 ****************************************************************************/
511
512 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
513 {
514         DEBUG(3,("Setting printer type=%s\n", handlename));
515
516         /* it's a print server */
517         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
518                 DEBUGADD(4,("Printer is a print server\n"));
519                 Printer->printer_type = SPLHND_SERVER;
520         }
521         /* it's a printer (set_printer_hnd_name() will handle port monitors */
522         else {
523                 DEBUGADD(4,("Printer is a printer\n"));
524                 Printer->printer_type = SPLHND_PRINTER;
525         }
526
527         return true;
528 }
529
530 static void prune_printername_cache_fn(const char *key, const char *value,
531                                        time_t timeout, void *private_data)
532 {
533         gencache_del(key);
534 }
535
536 static void prune_printername_cache(void)
537 {
538         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
539 }
540
541 /****************************************************************************
542  Set printer handle name..  Accept names like \\server, \\server\printer,
543  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
544  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
545  XcvDataPort() interface.
546 ****************************************************************************/
547
548 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
549                                    const struct auth_serversupplied_info *session_info,
550                                    struct messaging_context *msg_ctx,
551                                    struct printer_handle *Printer,
552                                    const char *handlename)
553 {
554         int snum;
555         int n_services=lp_numservices();
556         char *aprinter;
557         const char *printername;
558         const char *servername = NULL;
559         fstring sname;
560         bool found = false;
561         struct spoolss_PrinterInfo2 *info2 = NULL;
562         WERROR result;
563         char *p;
564
565         /*
566          * Hopefully nobody names his printers like this. Maybe \ or ,
567          * are illegal in printer names even?
568          */
569         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
570         char *cache_key;
571         char *tmp;
572
573         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
574                 (unsigned long)strlen(handlename)));
575
576         aprinter = CONST_DISCARD(char *, handlename);
577         if ( *handlename == '\\' ) {
578                 servername = canon_servername(handlename);
579                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
580                         *aprinter = '\0';
581                         aprinter++;
582                 }
583                 if (!is_myname_or_ipaddr(servername)) {
584                         return WERR_INVALID_PRINTER_NAME;
585                 }
586                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
587                 if (Printer->servername == NULL) {
588                         return WERR_NOMEM;
589                 }
590         }
591
592         if (Printer->printer_type == SPLHND_SERVER) {
593                 return WERR_OK;
594         }
595
596         if (Printer->printer_type != SPLHND_PRINTER) {
597                 return WERR_INVALID_HANDLE;
598         }
599
600         DEBUGADD(5, ("searching for [%s]\n", aprinter));
601
602         p = strchr(aprinter, ',');
603         if (p != NULL) {
604                 char *p2 = p;
605                 p++;
606                 if (*p == ' ') {
607                         p++;
608                 }
609                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
610                         *p2 = '\0';
611                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
612                         *p2 = '\0';
613                 }
614         }
615
616         if (p) {
617                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
618         }
619
620         /* check for the Port Monitor Interface */
621         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
622                 Printer->printer_type = SPLHND_PORTMON_TCP;
623                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
624                 found = true;
625         }
626         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
627                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
628                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
629                 found = true;
630         }
631
632         /*
633          * With hundreds of printers, the "for" loop iterating all
634          * shares can be quite expensive, as it is done on every
635          * OpenPrinter. The loop maps "aprinter" to "sname", the
636          * result of which we cache in gencache.
637          */
638
639         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
640                                     aprinter);
641         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
642
643                 found = (strcmp(tmp, printer_not_found) != 0);
644                 if (!found) {
645                         DEBUG(4, ("Printer %s not found\n", aprinter));
646                         SAFE_FREE(tmp);
647                         return WERR_INVALID_PRINTER_NAME;
648                 }
649                 fstrcpy(sname, tmp);
650                 SAFE_FREE(tmp);
651         }
652
653         /* Search all sharenames first as this is easier than pulling
654            the printer_info_2 off of disk. Don't use find_service() since
655            that calls out to map_username() */
656
657         /* do another loop to look for printernames */
658         for (snum = 0; !found && snum < n_services; snum++) {
659                 const char *printer = lp_const_servicename(snum);
660
661                 /* no point going on if this is not a printer */
662                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
663                         continue;
664                 }
665
666                 /* ignore [printers] share */
667                 if (strequal(printer, "printers")) {
668                         continue;
669                 }
670
671                 fstrcpy(sname, printer);
672                 if (strequal(aprinter, printer)) {
673                         found = true;
674                         break;
675                 }
676
677                 /* no point looking up the printer object if
678                    we aren't allowing printername != sharename */
679                 if (lp_force_printername(snum)) {
680                         continue;
681                 }
682
683                 result = winreg_get_printer(mem_ctx,
684                                             session_info,
685                                             msg_ctx,
686                                             sname,
687                                             &info2);
688                 if ( !W_ERROR_IS_OK(result) ) {
689                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
690                                  sname, win_errstr(result)));
691                         continue;
692                 }
693
694                 printername = strrchr(info2->printername, '\\');
695                 if (printername == NULL) {
696                         printername = info2->printername;
697                 } else {
698                         printername++;
699                 }
700
701                 if (strequal(printername, aprinter)) {
702                         found = true;
703                         break;
704                 }
705
706                 DEBUGADD(10, ("printername: %s\n", printername));
707
708                 TALLOC_FREE(info2);
709         }
710
711         if ( !found ) {
712                 if (cache_key != NULL) {
713                         gencache_set(cache_key, printer_not_found,
714                                      time(NULL)+300);
715                         TALLOC_FREE(cache_key);
716                 }
717                 DEBUGADD(4,("Printer not found\n"));
718                 return WERR_INVALID_PRINTER_NAME;
719         }
720
721         if (cache_key != NULL) {
722                 gencache_set(cache_key, sname, time(NULL)+300);
723                 TALLOC_FREE(cache_key);
724         }
725
726         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
727
728         fstrcpy(Printer->sharename, sname);
729
730         return WERR_OK;
731 }
732
733 /****************************************************************************
734  Find first available printer slot. creates a printer handle for you.
735  ****************************************************************************/
736
737 static WERROR open_printer_hnd(struct pipes_struct *p,
738                                struct policy_handle *hnd,
739                                const char *name,
740                                uint32_t access_granted)
741 {
742         struct printer_handle *new_printer;
743         WERROR result;
744
745         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
746
747         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
748         if (new_printer == NULL) {
749                 return WERR_NOMEM;
750         }
751         talloc_set_destructor(new_printer, printer_entry_destructor);
752
753         /* This also steals the printer_handle on the policy_handle */
754         if (!create_policy_hnd(p, hnd, new_printer)) {
755                 TALLOC_FREE(new_printer);
756                 return WERR_INVALID_HANDLE;
757         }
758
759         /* Add to the internal list. */
760         DLIST_ADD(printers_list, new_printer);
761
762         new_printer->notify.option=NULL;
763
764         if (!set_printer_hnd_printertype(new_printer, name)) {
765                 close_printer_handle(p, hnd);
766                 return WERR_INVALID_HANDLE;
767         }
768
769         result = set_printer_hnd_name(p->mem_ctx,
770                                       get_session_info_system(),
771                                       p->msg_ctx,
772                                       new_printer, name);
773         if (!W_ERROR_IS_OK(result)) {
774                 close_printer_handle(p, hnd);
775                 return result;
776         }
777
778         new_printer->access_granted = access_granted;
779
780         DEBUG(5, ("%d printer handles active\n",
781                   (int)num_pipe_handles(p)));
782
783         return WERR_OK;
784 }
785
786 /***************************************************************************
787  check to see if the client motify handle is monitoring the notification
788  given by (notify_type, notify_field).
789  **************************************************************************/
790
791 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
792                                       uint16_t notify_field)
793 {
794         return true;
795 }
796
797 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
798                                 uint16_t notify_field)
799 {
800         struct spoolss_NotifyOption *option = p->notify.option;
801         uint32_t i, j;
802
803         /*
804          * Flags should always be zero when the change notify
805          * is registered by the client's spooler.  A user Win32 app
806          * might use the flags though instead of the NOTIFY_OPTION_INFO
807          * --jerry
808          */
809
810         if (!option) {
811                 return false;
812         }
813
814         if (p->notify.flags)
815                 return is_monitoring_event_flags(
816                         p->notify.flags, notify_type, notify_field);
817
818         for (i = 0; i < option->count; i++) {
819
820                 /* Check match for notify_type */
821
822                 if (option->types[i].type != notify_type)
823                         continue;
824
825                 /* Check match for field */
826
827                 for (j = 0; j < option->types[i].count; j++) {
828                         if (option->types[i].fields[j].field == notify_field) {
829                                 return true;
830                         }
831                 }
832         }
833
834         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
835                    p->servername, p->sharename, notify_type, notify_field));
836
837         return false;
838 }
839
840 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
841         _data->data.integer[0] = _integer; \
842         _data->data.integer[1] = 0;
843
844
845 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
846         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
847         if (!_data->data.string.string) {\
848                 _data->data.string.size = 0; \
849         } \
850         _data->data.string.size = strlen_m_term(_p) * 2;
851
852 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
853         _data->data.devmode.devmode = _devmode;
854
855 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
856         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
857         if (!_data->data.sd.sd) { \
858                 _data->data.sd.sd_size = 0; \
859         } \
860         _data->data.sd.sd_size = \
861                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
862
863 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
864                                    struct tm *t,
865                                    const char **pp,
866                                    uint32_t *plen)
867 {
868         struct spoolss_Time st;
869         uint32_t len = 16;
870         char *p;
871
872         if (!init_systemtime(&st, t)) {
873                 return;
874         }
875
876         p = talloc_array(mem_ctx, char, len);
877         if (!p) {
878                 return;
879         }
880
881         /*
882          * Systemtime must be linearized as a set of UINT16's.
883          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
884          */
885
886         SSVAL(p, 0, st.year);
887         SSVAL(p, 2, st.month);
888         SSVAL(p, 4, st.day_of_week);
889         SSVAL(p, 6, st.day);
890         SSVAL(p, 8, st.hour);
891         SSVAL(p, 10, st.minute);
892         SSVAL(p, 12, st.second);
893         SSVAL(p, 14, st.millisecond);
894
895         *pp = p;
896         *plen = len;
897 }
898
899 /* Convert a notification message to a struct spoolss_Notify */
900
901 static void notify_one_value(struct spoolss_notify_msg *msg,
902                              struct spoolss_Notify *data,
903                              TALLOC_CTX *mem_ctx)
904 {
905         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
906 }
907
908 static void notify_string(struct spoolss_notify_msg *msg,
909                           struct spoolss_Notify *data,
910                           TALLOC_CTX *mem_ctx)
911 {
912         /* The length of the message includes the trailing \0 */
913
914         data->data.string.size = msg->len * 2;
915         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
916         if (!data->data.string.string) {
917                 data->data.string.size = 0;
918                 return;
919         }
920 }
921
922 static void notify_system_time(struct spoolss_notify_msg *msg,
923                                struct spoolss_Notify *data,
924                                TALLOC_CTX *mem_ctx)
925 {
926         data->data.string.string = NULL;
927         data->data.string.size = 0;
928
929         if (msg->len != sizeof(time_t)) {
930                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
931                           msg->len));
932                 return;
933         }
934
935         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
936                                &data->data.string.string,
937                                &data->data.string.size);
938 }
939
940 struct notify2_message_table {
941         const char *name;
942         void (*fn)(struct spoolss_notify_msg *msg,
943                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
944 };
945
946 static struct notify2_message_table printer_notify_table[] = {
947         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
948         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
949         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
950         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
951         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
952         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
953         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
954         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
955         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
956         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
957         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
958         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
959         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
960         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
961         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
962         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
963         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
964         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
965         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
966 };
967
968 static struct notify2_message_table job_notify_table[] = {
969         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
970         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
971         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
972         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
973         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
974         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
975         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
976         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
977         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
978         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
979         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
980         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
981         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
982         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
983         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
984         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
985         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
986         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
987         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
988         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
989         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
990         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
991         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
992         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
993 };
994
995
996 /***********************************************************************
997  Allocate talloc context for container object
998  **********************************************************************/
999
1000 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1001 {
1002         if ( !ctr )
1003                 return;
1004
1005         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1006
1007         return;
1008 }
1009
1010 /***********************************************************************
1011  release all allocated memory and zero out structure
1012  **********************************************************************/
1013
1014 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1015 {
1016         if ( !ctr )
1017                 return;
1018
1019         if ( ctr->ctx )
1020                 talloc_destroy(ctr->ctx);
1021
1022         ZERO_STRUCTP(ctr);
1023
1024         return;
1025 }
1026
1027 /***********************************************************************
1028  **********************************************************************/
1029
1030 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1031 {
1032         if ( !ctr )
1033                 return NULL;
1034
1035         return ctr->ctx;
1036 }
1037
1038 /***********************************************************************
1039  **********************************************************************/
1040
1041 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1042 {
1043         if ( !ctr || !ctr->msg_groups )
1044                 return NULL;
1045
1046         if ( idx >= ctr->num_groups )
1047                 return NULL;
1048
1049         return &ctr->msg_groups[idx];
1050
1051 }
1052
1053 /***********************************************************************
1054  How many groups of change messages do we have ?
1055  **********************************************************************/
1056
1057 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1058 {
1059         if ( !ctr )
1060                 return 0;
1061
1062         return ctr->num_groups;
1063 }
1064
1065 /***********************************************************************
1066  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1067  **********************************************************************/
1068
1069 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1070 {
1071         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1072         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1073         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1074         int                             i, new_slot;
1075
1076         if ( !ctr || !msg )
1077                 return 0;
1078
1079         /* loop over all groups looking for a matching printer name */
1080
1081         for ( i=0; i<ctr->num_groups; i++ ) {
1082                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1083                         break;
1084         }
1085
1086         /* add a new group? */
1087
1088         if ( i == ctr->num_groups ) {
1089                 ctr->num_groups++;
1090
1091                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1092                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1093                         return 0;
1094                 }
1095                 ctr->msg_groups = groups;
1096
1097                 /* clear the new entry and set the printer name */
1098
1099                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1100                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1101         }
1102
1103         /* add the change messages; 'i' is the correct index now regardless */
1104
1105         msg_grp = &ctr->msg_groups[i];
1106
1107         msg_grp->num_msgs++;
1108
1109         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1110                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1111                 return 0;
1112         }
1113         msg_grp->msgs = msg_list;
1114
1115         new_slot = msg_grp->num_msgs-1;
1116         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1117
1118         /* need to allocate own copy of data */
1119
1120         if ( msg->len != 0 )
1121                 msg_grp->msgs[new_slot].notify.data = (char *)
1122                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1123
1124         return ctr->num_groups;
1125 }
1126
1127 static void construct_info_data(struct spoolss_Notify *info_data,
1128                                 enum spoolss_NotifyType type,
1129                                 uint16_t field, int id);
1130
1131 /***********************************************************************
1132  Send a change notication message on all handles which have a call
1133  back registered
1134  **********************************************************************/
1135
1136 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1137                                   struct printer_handle *prn_hnd,
1138                                   SPOOLSS_NOTIFY_MSG *messages,
1139                                   uint32_t num_msgs,
1140                                   struct spoolss_Notify **_notifies,
1141                                   int *_count)
1142 {
1143         struct spoolss_Notify *notifies;
1144         SPOOLSS_NOTIFY_MSG *msg;
1145         int count = 0;
1146         uint32_t id;
1147         int i;
1148
1149         notifies = talloc_zero_array(mem_ctx,
1150                                      struct spoolss_Notify, num_msgs);
1151         if (!notifies) {
1152                 return ENOMEM;
1153         }
1154
1155         for (i = 0; i < num_msgs; i++) {
1156
1157                 msg = &messages[i];
1158
1159                 /* Are we monitoring this event? */
1160
1161                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1162                         continue;
1163                 }
1164
1165                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1166                            "for printer [%s]\n",
1167                            msg->type, msg->field, prn_hnd->sharename));
1168
1169                 /*
1170                  * if the is a printer notification handle and not a job
1171                  * notification type, then set the id to 0.
1172                  * Otherwise just use what was specified in the message.
1173                  *
1174                  * When registering change notification on a print server
1175                  * handle we always need to send back the id (snum) matching
1176                  * the printer for which the change took place.
1177                  * For change notify registered on a printer handle,
1178                  * this does not matter and the id should be 0.
1179                  *
1180                  * --jerry
1181                  */
1182
1183                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1184                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1185                         id = 0;
1186                 } else {
1187                         id = msg->id;
1188                 }
1189
1190                 /* Convert unix jobid to smb jobid */
1191
1192                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1193                         id = sysjob_to_jobid(msg->id);
1194
1195                         if (id == -1) {
1196                                 DEBUG(3, ("no such unix jobid %d\n",
1197                                           msg->id));
1198                                 continue;
1199                         }
1200                 }
1201
1202                 construct_info_data(&notifies[count],
1203                                     msg->type, msg->field, id);
1204
1205                 switch(msg->type) {
1206                 case PRINTER_NOTIFY_TYPE:
1207                         if (printer_notify_table[msg->field].fn) {
1208                                 printer_notify_table[msg->field].fn(msg,
1209                                                 &notifies[count], mem_ctx);
1210                         }
1211                         break;
1212
1213                 case JOB_NOTIFY_TYPE:
1214                         if (job_notify_table[msg->field].fn) {
1215                                 job_notify_table[msg->field].fn(msg,
1216                                                 &notifies[count], mem_ctx);
1217                         }
1218                         break;
1219
1220                 default:
1221                         DEBUG(5, ("Unknown notification type %d\n",
1222                                   msg->type));
1223                         continue;
1224                 }
1225
1226                 count++;
1227         }
1228
1229         *_notifies = notifies;
1230         *_count = count;
1231
1232         return 0;
1233 }
1234
1235 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1236                                 struct printer_handle *prn_hnd,
1237                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1238 {
1239         struct spoolss_Notify *notifies;
1240         int count = 0;
1241         union spoolss_ReplyPrinterInfo info;
1242         struct spoolss_NotifyInfo info0;
1243         uint32_t reply_result;
1244         NTSTATUS status;
1245         WERROR werr;
1246         int ret;
1247
1248         /* Is there notification on this handle? */
1249         if (prn_hnd->notify.cli_chan == NULL ||
1250             prn_hnd->notify.cli_chan->active_connections == 0) {
1251                 return 0;
1252         }
1253
1254         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1255                    prn_hnd->servername, prn_hnd->sharename));
1256
1257         /* For this printer? Print servers always receive notifications. */
1258         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1259             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1260                 return 0;
1261         }
1262
1263         DEBUG(10,("Our printer\n"));
1264
1265         /* build the array of change notifications */
1266         ret = build_notify2_messages(mem_ctx, prn_hnd,
1267                                      msg_group->msgs,
1268                                      msg_group->num_msgs,
1269                                      &notifies, &count);
1270         if (ret) {
1271                 return ret;
1272         }
1273
1274         info0.version   = 0x2;
1275         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1276         info0.count     = count;
1277         info0.notifies  = notifies;
1278
1279         info.info0 = &info0;
1280
1281         status = dcerpc_spoolss_RouterReplyPrinterEx(
1282                                 prn_hnd->notify.cli_chan->binding_handle,
1283                                 mem_ctx,
1284                                 &prn_hnd->notify.cli_hnd,
1285                                 prn_hnd->notify.change, /* color */
1286                                 prn_hnd->notify.flags,
1287                                 &reply_result,
1288                                 0, /* reply_type, must be 0 */
1289                                 info, &werr);
1290         if (!NT_STATUS_IS_OK(status)) {
1291                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1292                           "failed: %s\n",
1293                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1294                           nt_errstr(status)));
1295                 werr = ntstatus_to_werror(status);
1296         } else if (!W_ERROR_IS_OK(werr)) {
1297                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1298                           "failed: %s\n",
1299                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1300                           win_errstr(werr)));
1301         }
1302         switch (reply_result) {
1303         case 0:
1304                 break;
1305         case PRINTER_NOTIFY_INFO_DISCARDED:
1306         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1307         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1308                 break;
1309         default:
1310                 break;
1311         }
1312
1313         return 0;
1314 }
1315
1316 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1317 {
1318         struct printer_handle    *p;
1319         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1320         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1321         int ret;
1322
1323         if ( !msg_group ) {
1324                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1325                 return;
1326         }
1327
1328         if (!msg_group->msgs) {
1329                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1330                 return;
1331         }
1332
1333         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1334
1335         /* loop over all printers */
1336
1337         for (p = printers_list; p; p = p->next) {
1338                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1339                 if (ret) {
1340                         goto done;
1341                 }
1342         }
1343
1344 done:
1345         DEBUG(8,("send_notify2_changes: Exit...\n"));
1346         return;
1347 }
1348
1349 /***********************************************************************
1350  **********************************************************************/
1351
1352 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1353 {
1354
1355         uint32_t tv_sec, tv_usec;
1356         size_t offset = 0;
1357
1358         /* Unpack message */
1359
1360         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1361                              msg->printer);
1362
1363         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1364                                 &tv_sec, &tv_usec,
1365                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1366
1367         if (msg->len == 0)
1368                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1369                            &msg->notify.value[0], &msg->notify.value[1]);
1370         else
1371                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1372                            &msg->len, &msg->notify.data);
1373
1374         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1375                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1376
1377         tv->tv_sec = tv_sec;
1378         tv->tv_usec = tv_usec;
1379
1380         if (msg->len == 0)
1381                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1382                           msg->notify.value[1]));
1383         else
1384                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1385
1386         return true;
1387 }
1388
1389 /********************************************************************
1390  Receive a notify2 message list
1391  ********************************************************************/
1392
1393 static void receive_notify2_message_list(struct messaging_context *msg,
1394                                          void *private_data,
1395                                          uint32_t msg_type,
1396                                          struct server_id server_id,
1397                                          DATA_BLOB *data)
1398 {
1399         size_t                  msg_count, i;
1400         char                    *buf = (char *)data->data;
1401         char                    *msg_ptr;
1402         size_t                  msg_len;
1403         SPOOLSS_NOTIFY_MSG      notify;
1404         SPOOLSS_NOTIFY_MSG_CTR  messages;
1405         int                     num_groups;
1406
1407         if (data->length < 4) {
1408                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1409                 return;
1410         }
1411
1412         msg_count = IVAL(buf, 0);
1413         msg_ptr = buf + 4;
1414
1415         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1416
1417         if (msg_count == 0) {
1418                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1419                 return;
1420         }
1421
1422         /* initialize the container */
1423
1424         ZERO_STRUCT( messages );
1425         notify_msg_ctr_init( &messages );
1426
1427         /*
1428          * build message groups for each printer identified
1429          * in a change_notify msg.  Remember that a PCN message
1430          * includes the handle returned for the srv_spoolss_replyopenprinter()
1431          * call.  Therefore messages are grouped according to printer handle.
1432          */
1433
1434         for ( i=0; i<msg_count; i++ ) {
1435                 struct timeval msg_tv;
1436
1437                 if (msg_ptr + 4 - buf > data->length) {
1438                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1439                         return;
1440                 }
1441
1442                 msg_len = IVAL(msg_ptr,0);
1443                 msg_ptr += 4;
1444
1445                 if (msg_ptr + msg_len - buf > data->length) {
1446                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1447                         return;
1448                 }
1449
1450                 /* unpack messages */
1451
1452                 ZERO_STRUCT( notify );
1453                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1454                 msg_ptr += msg_len;
1455
1456                 /* add to correct list in container */
1457
1458                 notify_msg_ctr_addmsg( &messages, &notify );
1459
1460                 /* free memory that might have been allocated by notify2_unpack_msg() */
1461
1462                 if ( notify.len != 0 )
1463                         SAFE_FREE( notify.notify.data );
1464         }
1465
1466         /* process each group of messages */
1467
1468         num_groups = notify_msg_ctr_numgroups( &messages );
1469         for ( i=0; i<num_groups; i++ )
1470                 send_notify2_changes( &messages, i );
1471
1472
1473         /* cleanup */
1474
1475         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1476                 (uint32_t)msg_count ));
1477
1478         notify_msg_ctr_destroy( &messages );
1479
1480         return;
1481 }
1482
1483 /********************************************************************
1484  Send a message to ourself about new driver being installed
1485  so we can upgrade the information for each printer bound to this
1486  driver
1487  ********************************************************************/
1488
1489 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1490                                             struct messaging_context *msg_ctx)
1491 {
1492         int len = strlen(drivername);
1493
1494         if (!len)
1495                 return false;
1496
1497         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1498                 drivername));
1499
1500         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1501                            MSG_PRINTER_DRVUPGRADE,
1502                            (uint8_t *)drivername, len+1);
1503
1504         return true;
1505 }
1506
1507 void srv_spoolss_cleanup(void)
1508 {
1509         struct printer_session_counter *session_counter;
1510
1511         for (session_counter = counter_list;
1512              session_counter != NULL;
1513              session_counter = counter_list) {
1514                 DLIST_REMOVE(counter_list, session_counter);
1515                 TALLOC_FREE(session_counter);
1516         }
1517 }
1518
1519 /**********************************************************************
1520  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1521  over all printers, upgrading ones as necessary
1522  **********************************************************************/
1523
1524 void do_drv_upgrade_printer(struct messaging_context *msg,
1525                             void *private_data,
1526                             uint32_t msg_type,
1527                             struct server_id server_id,
1528                             DATA_BLOB *data)
1529 {
1530         TALLOC_CTX *tmp_ctx;
1531         struct auth_serversupplied_info *session_info = NULL;
1532         struct spoolss_PrinterInfo2 *pinfo2;
1533         NTSTATUS status;
1534         WERROR result;
1535         const char *drivername;
1536         int snum;
1537         int n_services = lp_numservices();
1538
1539         tmp_ctx = talloc_new(NULL);
1540         if (!tmp_ctx) return;
1541
1542         status = make_session_info_system(tmp_ctx, &session_info);
1543         if (!NT_STATUS_IS_OK(status)) {
1544                 DEBUG(0, ("do_drv_upgrade_printer: "
1545                           "Could not create system session_info\n"));
1546                 goto done;
1547         }
1548
1549         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1550         if (!drivername) {
1551                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1552                 goto done;
1553         }
1554
1555         DEBUG(10, ("do_drv_upgrade_printer: "
1556                    "Got message for new driver [%s]\n", drivername));
1557
1558         /* Iterate the printer list */
1559
1560         for (snum = 0; snum < n_services; snum++) {
1561                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1562                         continue;
1563                 }
1564
1565                 /* ignore [printers] share */
1566                 if (strequal(lp_const_servicename(snum), "printers")) {
1567                         continue;
1568                 }
1569
1570                 result = winreg_get_printer(tmp_ctx, session_info, msg,
1571                                             lp_const_servicename(snum),
1572                                             &pinfo2);
1573
1574                 if (!W_ERROR_IS_OK(result)) {
1575                         continue;
1576                 }
1577
1578                 if (!pinfo2->drivername) {
1579                         continue;
1580                 }
1581
1582                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1583                         continue;
1584                 }
1585
1586                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1587
1588                 /* all we care about currently is the change_id */
1589                 result = winreg_printer_update_changeid(tmp_ctx,
1590                                                         session_info,
1591                                                         msg,
1592                                                         pinfo2->printername);
1593
1594                 if (!W_ERROR_IS_OK(result)) {
1595                         DEBUG(3, ("do_drv_upgrade_printer: "
1596                                   "Failed to update changeid [%s]\n",
1597                                   win_errstr(result)));
1598                 }
1599         }
1600
1601         /* all done */
1602 done:
1603         talloc_free(tmp_ctx);
1604 }
1605
1606 /********************************************************************
1607  Update the cache for all printq's with a registered client
1608  connection
1609  ********************************************************************/
1610
1611 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1612 {
1613         struct printer_handle *printer = printers_list;
1614         int snum;
1615
1616         /* loop through all printers and update the cache where
1617            a client is connected */
1618         while (printer) {
1619                 if ((printer->printer_type == SPLHND_PRINTER) &&
1620                     ((printer->notify.cli_chan != NULL) &&
1621                      (printer->notify.cli_chan->active_connections > 0))) {
1622                         snum = print_queue_snum(printer->sharename);
1623                         print_queue_status(msg_ctx, snum, NULL, NULL);
1624                 }
1625
1626                 printer = printer->next;
1627         }
1628
1629         return;
1630 }
1631
1632 /****************************************************************
1633  _spoolss_OpenPrinter
1634 ****************************************************************/
1635
1636 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1637                             struct spoolss_OpenPrinter *r)
1638 {
1639         struct spoolss_OpenPrinterEx e;
1640         WERROR werr;
1641
1642         ZERO_STRUCT(e.in.userlevel);
1643
1644         e.in.printername        = r->in.printername;
1645         e.in.datatype           = r->in.datatype;
1646         e.in.devmode_ctr        = r->in.devmode_ctr;
1647         e.in.access_mask        = r->in.access_mask;
1648         e.in.level              = 0;
1649
1650         e.out.handle            = r->out.handle;
1651
1652         werr = _spoolss_OpenPrinterEx(p, &e);
1653
1654         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1655                 /* OpenPrinterEx returns this for a bad
1656                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1657                  * instead.
1658                  */
1659                 werr = WERR_INVALID_PRINTER_NAME;
1660         }
1661
1662         return werr;
1663 }
1664
1665 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1666                               struct spoolss_DeviceMode *orig,
1667                               struct spoolss_DeviceMode **dest)
1668 {
1669         struct spoolss_DeviceMode *dm;
1670
1671         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1672         if (!dm) {
1673                 return WERR_NOMEM;
1674         }
1675
1676         /* copy all values, then duplicate strings and structs */
1677         *dm = *orig;
1678
1679         dm->devicename = talloc_strdup(dm, orig->devicename);
1680         if (!dm->devicename) {
1681                 return WERR_NOMEM;
1682         }
1683         dm->formname = talloc_strdup(dm, orig->formname);
1684         if (!dm->formname) {
1685                 return WERR_NOMEM;
1686         }
1687         if (orig->driverextra_data.data) {
1688                 dm->driverextra_data.data =
1689                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1690                                         orig->driverextra_data.length);
1691                 if (!dm->driverextra_data.data) {
1692                         return WERR_NOMEM;
1693                 }
1694         }
1695
1696         *dest = dm;
1697         return WERR_OK;
1698 }
1699
1700 /****************************************************************
1701  _spoolss_OpenPrinterEx
1702 ****************************************************************/
1703
1704 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1705                               struct spoolss_OpenPrinterEx *r)
1706 {
1707         int snum;
1708         struct printer_handle *Printer=NULL;
1709         WERROR result;
1710
1711         if (!r->in.printername) {
1712                 return WERR_INVALID_PARAM;
1713         }
1714
1715         if (r->in.level > 3) {
1716                 return WERR_INVALID_PARAM;
1717         }
1718         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1719             (r->in.level == 2 && !r->in.userlevel.level2) ||
1720             (r->in.level == 3 && !r->in.userlevel.level3)) {
1721                 return WERR_INVALID_PARAM;
1722         }
1723
1724         /* some sanity check because you can open a printer or a print server */
1725         /* aka: \\server\printer or \\server */
1726
1727         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1728
1729         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1730         if (!W_ERROR_IS_OK(result)) {
1731                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1732                         "for printer %s\n", r->in.printername));
1733                 ZERO_STRUCTP(r->out.handle);
1734                 return result;
1735         }
1736
1737         Printer = find_printer_index_by_hnd(p, r->out.handle);
1738         if ( !Printer ) {
1739                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1740                         "handle we created for printer %s\n", r->in.printername));
1741                 close_printer_handle(p, r->out.handle);
1742                 ZERO_STRUCTP(r->out.handle);
1743                 return WERR_INVALID_PARAM;
1744         }
1745
1746         /*
1747          * First case: the user is opening the print server:
1748          *
1749          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1750          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1751          *
1752          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1753          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1754          * or if the user is listed in the smb.conf printer admin parameter.
1755          *
1756          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1757          * client view printer folder, but does not show the MSAPW.
1758          *
1759          * Note: this test needs code to check access rights here too. Jeremy
1760          * could you look at this?
1761          *
1762          * Second case: the user is opening a printer:
1763          * NT doesn't let us connect to a printer if the connecting user
1764          * doesn't have print permission.
1765          *
1766          * Third case: user is opening a Port Monitor
1767          * access checks same as opening a handle to the print server.
1768          */
1769
1770         switch (Printer->printer_type )
1771         {
1772         case SPLHND_SERVER:
1773         case SPLHND_PORTMON_TCP:
1774         case SPLHND_PORTMON_LOCAL:
1775                 /* Printserver handles use global struct... */
1776
1777                 snum = -1;
1778
1779                 /* Map standard access rights to object specific access rights */
1780
1781                 se_map_standard(&r->in.access_mask,
1782                                 &printserver_std_mapping);
1783
1784                 /* Deny any object specific bits that don't apply to print
1785                    servers (i.e printer and job specific bits) */
1786
1787                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1788
1789                 if (r->in.access_mask &
1790                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1791                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1792                         close_printer_handle(p, r->out.handle);
1793                         ZERO_STRUCTP(r->out.handle);
1794                         return WERR_ACCESS_DENIED;
1795                 }
1796
1797                 /* Allow admin access */
1798
1799                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1800                 {
1801                         if (!lp_ms_add_printer_wizard()) {
1802                                 close_printer_handle(p, r->out.handle);
1803                                 ZERO_STRUCTP(r->out.handle);
1804                                 return WERR_ACCESS_DENIED;
1805                         }
1806
1807                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1808                            and not a printer admin, then fail */
1809
1810                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1811                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1812                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1813                             !token_contains_name_in_list(
1814                                     uidtoname(p->session_info->utok.uid),
1815                                     p->session_info->info3->base.domain.string,
1816                                     NULL,
1817                                     p->session_info->security_token,
1818                                     lp_printer_admin(snum))) {
1819                                 close_printer_handle(p, r->out.handle);
1820                                 ZERO_STRUCTP(r->out.handle);
1821                                 DEBUG(3,("access DENIED as user is not root, "
1822                                         "has no printoperator privilege, "
1823                                         "not a member of the printoperator builtin group and "
1824                                         "is not in printer admin list"));
1825                                 return WERR_ACCESS_DENIED;
1826                         }
1827
1828                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1829                 }
1830                 else
1831                 {
1832                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1833                 }
1834
1835                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1836                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1837
1838                 /* We fall through to return WERR_OK */
1839                 break;
1840
1841         case SPLHND_PRINTER:
1842                 /* NT doesn't let us connect to a printer if the connecting user
1843                    doesn't have print permission.  */
1844
1845                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1846                         close_printer_handle(p, r->out.handle);
1847                         ZERO_STRUCTP(r->out.handle);
1848                         return WERR_BADFID;
1849                 }
1850
1851                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1852                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1853                 }
1854
1855                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1856
1857                 /* map an empty access mask to the minimum access mask */
1858                 if (r->in.access_mask == 0x0)
1859                         r->in.access_mask = PRINTER_ACCESS_USE;
1860
1861                 /*
1862                  * If we are not serving the printer driver for this printer,
1863                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1864                  * will keep NT clients happy  --jerry
1865                  */
1866
1867                 if (lp_use_client_driver(snum)
1868                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1869                 {
1870                         r->in.access_mask = PRINTER_ACCESS_USE;
1871                 }
1872
1873                 /* check smb.conf parameters and the the sec_desc */
1874
1875                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1876                                   p->client_id->name, p->client_id->addr)) {
1877                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1878                         ZERO_STRUCTP(r->out.handle);
1879                         return WERR_ACCESS_DENIED;
1880                 }
1881
1882                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1883                                    p->session_info->security_token, snum) ||
1884                     !print_access_check(p->session_info,
1885                                         p->msg_ctx,
1886                                         snum,
1887                                         r->in.access_mask)) {
1888                         DEBUG(3, ("access DENIED for printer open\n"));
1889                         close_printer_handle(p, r->out.handle);
1890                         ZERO_STRUCTP(r->out.handle);
1891                         return WERR_ACCESS_DENIED;
1892                 }
1893
1894                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1895                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1896                         close_printer_handle(p, r->out.handle);
1897                         ZERO_STRUCTP(r->out.handle);
1898                         return WERR_ACCESS_DENIED;
1899                 }
1900
1901                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1902                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1903                 else
1904                         r->in.access_mask = PRINTER_ACCESS_USE;
1905
1906                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1907                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1908
1909                 winreg_create_printer(p->mem_ctx,
1910                                       get_session_info_system(),
1911                                       p->msg_ctx,
1912                                       lp_const_servicename(snum));
1913
1914                 break;
1915
1916         default:
1917                 /* sanity check to prevent programmer error */
1918                 ZERO_STRUCTP(r->out.handle);
1919                 return WERR_BADFID;
1920         }
1921
1922         Printer->access_granted = r->in.access_mask;
1923
1924         /*
1925          * If the client sent a devmode in the OpenPrinter() call, then
1926          * save it here in case we get a job submission on this handle
1927          */
1928
1929          if ((Printer->printer_type != SPLHND_SERVER) &&
1930              r->in.devmode_ctr.devmode) {
1931                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1932                                 &Printer->devmode);
1933          }
1934
1935 #if 0   /* JERRY -- I'm doubtful this is really effective */
1936         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1937            optimization in Windows 2000 clients  --jerry */
1938
1939         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1940                 && (RA_WIN2K == get_remote_arch()) )
1941         {
1942                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1943                 sys_usleep( 500000 );
1944         }
1945 #endif
1946
1947         return WERR_OK;
1948 }
1949
1950 /****************************************************************
1951  _spoolss_ClosePrinter
1952 ****************************************************************/
1953
1954 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1955                              struct spoolss_ClosePrinter *r)
1956 {
1957         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1958
1959         if (Printer && Printer->document_started) {
1960                 struct spoolss_EndDocPrinter e;
1961
1962                 e.in.handle = r->in.handle;
1963
1964                 _spoolss_EndDocPrinter(p, &e);
1965         }
1966
1967         if (!close_printer_handle(p, r->in.handle))
1968                 return WERR_BADFID;
1969
1970         /* clear the returned printer handle.  Observed behavior
1971            from Win2k server.  Don't think this really matters.
1972            Previous code just copied the value of the closed
1973            handle.    --jerry */
1974
1975         ZERO_STRUCTP(r->out.handle);
1976
1977         return WERR_OK;
1978 }
1979
1980 /****************************************************************
1981  _spoolss_DeletePrinter
1982 ****************************************************************/
1983
1984 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1985                               struct spoolss_DeletePrinter *r)
1986 {
1987         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1988         WERROR result;
1989         int snum;
1990
1991         if (Printer && Printer->document_started) {
1992                 struct spoolss_EndDocPrinter e;
1993
1994                 e.in.handle = r->in.handle;
1995
1996                 _spoolss_EndDocPrinter(p, &e);
1997         }
1998
1999         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2000                 winreg_delete_printer_key(p->mem_ctx,
2001                                           get_session_info_system(),
2002                                           p->msg_ctx,
2003                                           lp_const_servicename(snum),
2004                                           "");
2005         }
2006
2007         result = delete_printer_handle(p, r->in.handle);
2008
2009         return result;
2010 }
2011
2012 /*******************************************************************
2013  * static function to lookup the version id corresponding to an
2014  * long architecture string
2015  ******************************************************************/
2016
2017 static const struct print_architecture_table_node archi_table[]= {
2018
2019         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2020         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2021         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2022         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2023         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2024         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2025         {"Windows x64",          SPL_ARCH_X64,          3 },
2026         {NULL,                   "",            -1 }
2027 };
2028
2029 static int get_version_id(const char *arch)
2030 {
2031         int i;
2032
2033         for (i=0; archi_table[i].long_archi != NULL; i++)
2034         {
2035                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2036                         return (archi_table[i].version);
2037         }
2038
2039         return -1;
2040 }
2041
2042 /****************************************************************
2043  _spoolss_DeletePrinterDriver
2044 ****************************************************************/
2045
2046 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2047                                     struct spoolss_DeletePrinterDriver *r)
2048 {
2049
2050         struct spoolss_DriverInfo8 *info = NULL;
2051         struct spoolss_DriverInfo8 *info_win2k = NULL;
2052         int                             version;
2053         WERROR                          status;
2054
2055         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2056            and not a printer admin, then fail */
2057
2058         if ( (p->session_info->utok.uid != sec_initial_uid())
2059              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2060                 && !token_contains_name_in_list(
2061                         uidtoname(p->session_info->utok.uid),
2062                         p->session_info->info3->base.domain.string,
2063                         NULL,
2064                         p->session_info->security_token,
2065                         lp_printer_admin(-1)) )
2066         {
2067                 return WERR_ACCESS_DENIED;
2068         }
2069
2070         /* check that we have a valid driver name first */
2071
2072         if ((version = get_version_id(r->in.architecture)) == -1)
2073                 return WERR_INVALID_ENVIRONMENT;
2074
2075         status = winreg_get_driver(p->mem_ctx,
2076                                    get_session_info_system(),
2077                                    p->msg_ctx,
2078                                    r->in.architecture, r->in.driver,
2079                                    version, &info);
2080         if (!W_ERROR_IS_OK(status)) {
2081                 /* try for Win2k driver if "Windows NT x86" */
2082
2083                 if ( version == 2 ) {
2084                         version = 3;
2085
2086                         status = winreg_get_driver(p->mem_ctx,
2087                                                    get_session_info_system(),
2088                                                    p->msg_ctx,
2089                                                    r->in.architecture,
2090                                                    r->in.driver,
2091                                                    version, &info);
2092                         if (!W_ERROR_IS_OK(status)) {
2093                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2094                                 goto done;
2095                         }
2096                 }
2097                 /* otherwise it was a failure */
2098                 else {
2099                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2100                         goto done;
2101                 }
2102
2103         }
2104
2105         if (printer_driver_in_use(p->mem_ctx,
2106                                   get_session_info_system(),
2107                                   p->msg_ctx,
2108                                   info)) {
2109                 status = WERR_PRINTER_DRIVER_IN_USE;
2110                 goto done;
2111         }
2112
2113         if (version == 2) {
2114                 status = winreg_get_driver(p->mem_ctx,
2115                                            get_session_info_system(),
2116                                            p->msg_ctx,
2117                                            r->in.architecture,
2118                                            r->in.driver, 3, &info_win2k);
2119                 if (W_ERROR_IS_OK(status)) {
2120                         /* if we get to here, we now have 2 driver info structures to remove */
2121                         /* remove the Win2k driver first*/
2122
2123                         status = winreg_del_driver(p->mem_ctx,
2124                                                    get_session_info_system(),
2125                                                    p->msg_ctx,
2126                                                    info_win2k, 3);
2127                         talloc_free(info_win2k);
2128
2129                         /* this should not have failed---if it did, report to client */
2130                         if (!W_ERROR_IS_OK(status)) {
2131                                 goto done;
2132                         }
2133                 }
2134         }
2135
2136         status = winreg_del_driver(p->mem_ctx,
2137                                    get_session_info_system(),
2138                                    p->msg_ctx,
2139                                    info, version);
2140
2141 done:
2142         talloc_free(info);
2143
2144         return status;
2145 }
2146
2147 /****************************************************************
2148  _spoolss_DeletePrinterDriverEx
2149 ****************************************************************/
2150
2151 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2152                                       struct spoolss_DeletePrinterDriverEx *r)
2153 {
2154         struct spoolss_DriverInfo8      *info = NULL;
2155         struct spoolss_DriverInfo8      *info_win2k = NULL;
2156         int                             version;
2157         bool                            delete_files;
2158         WERROR                          status;
2159
2160         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2161            and not a printer admin, then fail */
2162
2163         if ( (p->session_info->utok.uid != sec_initial_uid())
2164                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2165                 && !token_contains_name_in_list(
2166                         uidtoname(p->session_info->utok.uid),
2167                         p->session_info->info3->base.domain.string,
2168                         NULL,
2169                         p->session_info->security_token, lp_printer_admin(-1)) )
2170         {
2171                 return WERR_ACCESS_DENIED;
2172         }
2173
2174         /* check that we have a valid driver name first */
2175         if ((version = get_version_id(r->in.architecture)) == -1) {
2176                 /* this is what NT returns */
2177                 return WERR_INVALID_ENVIRONMENT;
2178         }
2179
2180         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2181                 version = r->in.version;
2182
2183         status = winreg_get_driver(p->mem_ctx,
2184                                    get_session_info_system(),
2185                                    p->msg_ctx,
2186                                    r->in.architecture,
2187                                    r->in.driver,
2188                                    version,
2189                                    &info);
2190         if (!W_ERROR_IS_OK(status)) {
2191                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2192
2193                 /*
2194                  * if the client asked for a specific version,
2195                  * or this is something other than Windows NT x86,
2196                  * then we've failed
2197                  */
2198
2199                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2200                         goto done;
2201
2202                 /* try for Win2k driver if "Windows NT x86" */
2203
2204                 version = 3;
2205                 status = winreg_get_driver(info,
2206                                            get_session_info_system(),
2207                                            p->msg_ctx,
2208                                            r->in.architecture,
2209                                            r->in.driver,
2210                                            version, &info);
2211                 if (!W_ERROR_IS_OK(status)) {
2212                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2213                         goto done;
2214                 }
2215         }
2216
2217         if (printer_driver_in_use(info,
2218                                   get_session_info_system(),
2219                                   p->msg_ctx,
2220                                   info)) {
2221                 status = WERR_PRINTER_DRIVER_IN_USE;
2222                 goto done;
2223         }
2224
2225         /*
2226          * we have a couple of cases to consider.
2227          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2228          *     then the delete should fail if **any** files overlap with
2229          *     other drivers
2230          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2231          *     non-overlapping files
2232          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2233          *     is set, the do not delete any files
2234          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2235          */
2236
2237         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2238
2239         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2240
2241         if (delete_files &&
2242             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2243             printer_driver_files_in_use(info,
2244                                         get_session_info_system(),
2245                                         p->msg_ctx,
2246                                         info)) {
2247                 /* no idea of the correct error here */
2248                 status = WERR_ACCESS_DENIED;
2249                 goto done;
2250         }
2251
2252
2253         /* also check for W32X86/3 if necessary; maybe we already have? */
2254
2255         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2256                 status = winreg_get_driver(info,
2257                                            get_session_info_system(),
2258                                            p->msg_ctx,
2259                                            r->in.architecture,
2260                                            r->in.driver, 3, &info_win2k);
2261                 if (W_ERROR_IS_OK(status)) {
2262
2263                         if (delete_files &&
2264                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2265                             printer_driver_files_in_use(info,
2266                                                         get_session_info_system(),
2267                                                         p->msg_ctx,
2268                                                         info_win2k)) {
2269                                 /* no idea of the correct error here */
2270                                 talloc_free(info_win2k);
2271                                 status = WERR_ACCESS_DENIED;
2272                                 goto done;
2273                         }
2274
2275                         /* if we get to here, we now have 2 driver info structures to remove */
2276                         /* remove the Win2k driver first*/
2277
2278                         status = winreg_del_driver(info,
2279                                                    get_session_info_system(),
2280                                                    p->msg_ctx,
2281                                                    info_win2k,
2282                                                    3);
2283
2284                         /* this should not have failed---if it did, report to client */
2285
2286                         if (!W_ERROR_IS_OK(status)) {
2287                                 goto done;
2288                         }
2289
2290                         /*
2291                          * now delete any associated files if delete_files is
2292                          * true. Even if this part failes, we return succes
2293                          * because the driver doesn not exist any more
2294                          */
2295                         if (delete_files) {
2296                                 delete_driver_files(get_session_info_system(),
2297                                                     info_win2k);
2298                         }
2299                 }
2300         }
2301
2302         status = winreg_del_driver(info,
2303                                    get_session_info_system(),
2304                                    p->msg_ctx,
2305                                    info,
2306                                    version);
2307         if (!W_ERROR_IS_OK(status)) {
2308                 goto done;
2309         }
2310
2311         /*
2312          * now delete any associated files if delete_files is
2313          * true. Even if this part failes, we return succes
2314          * because the driver doesn not exist any more
2315          */
2316         if (delete_files) {
2317                 delete_driver_files(get_session_info_system(), info);
2318         }
2319
2320 done:
2321         talloc_free(info);
2322         return status;
2323 }
2324
2325
2326 /********************************************************************
2327  GetPrinterData on a printer server Handle.
2328 ********************************************************************/
2329
2330 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2331                                             const char *value,
2332                                             enum winreg_Type *type,
2333                                             union spoolss_PrinterData *data)
2334 {
2335         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2336
2337         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2338                 *type = REG_DWORD;
2339                 data->value = 0x00;
2340                 return WERR_OK;
2341         }
2342
2343         if (!StrCaseCmp(value, "BeepEnabled")) {
2344                 *type = REG_DWORD;
2345                 data->value = 0x00;
2346                 return WERR_OK;
2347         }
2348
2349         if (!StrCaseCmp(value, "EventLog")) {
2350                 *type = REG_DWORD;
2351                 /* formally was 0x1b */
2352                 data->value = 0x00;
2353                 return WERR_OK;
2354         }
2355
2356         if (!StrCaseCmp(value, "NetPopup")) {
2357                 *type = REG_DWORD;
2358                 data->value = 0x00;
2359                 return WERR_OK;
2360         }
2361
2362         if (!StrCaseCmp(value, "MajorVersion")) {
2363                 *type = REG_DWORD;
2364
2365                 /* Windows NT 4.0 seems to not allow uploading of drivers
2366                    to a server that reports 0x3 as the MajorVersion.
2367                    need to investigate more how Win2k gets around this .
2368                    -- jerry */
2369
2370                 if (RA_WINNT == get_remote_arch()) {
2371                         data->value = 0x02;
2372                 } else {
2373                         data->value = 0x03;
2374                 }
2375
2376                 return WERR_OK;
2377         }
2378
2379         if (!StrCaseCmp(value, "MinorVersion")) {
2380                 *type = REG_DWORD;
2381                 data->value = 0x00;
2382                 return WERR_OK;
2383         }
2384
2385         /* REG_BINARY
2386          *  uint32_t size        = 0x114
2387          *  uint32_t major       = 5
2388          *  uint32_t minor       = [0|1]
2389          *  uint32_t build       = [2195|2600]
2390          *  extra unicode string = e.g. "Service Pack 3"
2391          */
2392         if (!StrCaseCmp(value, "OSVersion")) {
2393                 DATA_BLOB blob;
2394                 enum ndr_err_code ndr_err;
2395                 struct spoolss_OSVersion os;
2396
2397                 os.major                = 5;    /* Windows 2000 == 5.0 */
2398                 os.minor                = 0;
2399                 os.build                = 2195; /* build */
2400                 os.extra_string         = "";   /* leave extra string empty */
2401
2402                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2403                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2404                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2405                         return WERR_GENERAL_FAILURE;
2406                 }
2407
2408                 *type = REG_BINARY;
2409                 data->binary = blob;
2410
2411                 return WERR_OK;
2412         }
2413
2414
2415         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2416                 *type = REG_SZ;
2417
2418                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2419                 W_ERROR_HAVE_NO_MEMORY(data->string);
2420
2421                 return WERR_OK;
2422         }
2423
2424         if (!StrCaseCmp(value, "Architecture")) {
2425                 *type = REG_SZ;
2426                 data->string = talloc_strdup(mem_ctx,
2427                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2428                 W_ERROR_HAVE_NO_MEMORY(data->string);
2429
2430                 return WERR_OK;
2431         }
2432
2433         if (!StrCaseCmp(value, "DsPresent")) {
2434                 *type = REG_DWORD;
2435
2436                 /* only show the publish check box if we are a
2437                    member of a AD domain */
2438
2439                 if (lp_security() == SEC_ADS) {
2440                         data->value = 0x01;
2441                 } else {
2442                         data->value = 0x00;
2443                 }
2444                 return WERR_OK;
2445         }
2446
2447         if (!StrCaseCmp(value, "DNSMachineName")) {
2448                 const char *hostname = get_mydnsfullname();
2449
2450                 if (!hostname) {
2451                         return WERR_BADFILE;
2452                 }
2453
2454                 *type = REG_SZ;
2455                 data->string = talloc_strdup(mem_ctx, hostname);
2456                 W_ERROR_HAVE_NO_MEMORY(data->string);
2457
2458                 return WERR_OK;
2459         }
2460
2461         *type = REG_NONE;
2462
2463         return WERR_INVALID_PARAM;
2464 }
2465
2466 /****************************************************************
2467  _spoolss_GetPrinterData
2468 ****************************************************************/
2469
2470 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2471                                struct spoolss_GetPrinterData *r)
2472 {
2473         struct spoolss_GetPrinterDataEx r2;
2474
2475         r2.in.handle            = r->in.handle;
2476         r2.in.key_name          = "PrinterDriverData";
2477         r2.in.value_name        = r->in.value_name;
2478         r2.in.offered           = r->in.offered;
2479         r2.out.type             = r->out.type;
2480         r2.out.data             = r->out.data;
2481         r2.out.needed           = r->out.needed;
2482
2483         return _spoolss_GetPrinterDataEx(p, &r2);
2484 }
2485
2486 /*********************************************************
2487  Connect to the client machine.
2488 **********************************************************/
2489
2490 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2491                         struct sockaddr_storage *client_ss, const char *remote_machine)
2492 {
2493         NTSTATUS ret;
2494         struct cli_state *the_cli;
2495         struct sockaddr_storage rm_addr;
2496         char addr[INET6_ADDRSTRLEN];
2497
2498         if ( is_zero_addr(client_ss) ) {
2499                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2500                         remote_machine));
2501                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2502                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2503                         return false;
2504                 }
2505                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2506         } else {
2507                 rm_addr = *client_ss;
2508                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2509                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2510                         addr));
2511         }
2512
2513         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2514                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2515                         addr));
2516                 return false;
2517         }
2518
2519         /* setup the connection */
2520         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2521                 &rm_addr, 0, "IPC$", "IPC",
2522                 "", /* username */
2523                 "", /* domain */
2524                 "", /* password */
2525                 0, lp_client_signing());
2526
2527         if ( !NT_STATUS_IS_OK( ret ) ) {
2528                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2529                         remote_machine ));
2530                 return false;
2531         }
2532
2533         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2534                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2535                 cli_shutdown(the_cli);
2536                 return false;
2537         }
2538
2539         /*
2540          * Ok - we have an anonymous connection to the IPC$ share.
2541          * Now start the NT Domain stuff :-).
2542          */
2543
2544         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2545         if (!NT_STATUS_IS_OK(ret)) {
2546                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2547                         remote_machine, nt_errstr(ret)));
2548                 cli_shutdown(the_cli);
2549                 return false;
2550         }
2551
2552         return true;
2553 }
2554
2555 /***************************************************************************
2556  Connect to the client.
2557 ****************************************************************************/
2558
2559 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2560                                         uint32_t localprinter,
2561                                         enum winreg_Type type,
2562                                         struct policy_handle *handle,
2563                                         struct notify_back_channel **_chan,
2564                                         struct sockaddr_storage *client_ss,
2565                                         struct messaging_context *msg_ctx)
2566 {
2567         WERROR result;
2568         NTSTATUS status;
2569         struct notify_back_channel *chan;
2570
2571         for (chan = back_channels; chan; chan = chan->next) {
2572                 if (memcmp(&chan->client_address, client_ss,
2573                            sizeof(struct sockaddr_storage)) == 0) {
2574                         break;
2575                 }
2576         }
2577
2578         /*
2579          * If it's the first connection, contact the client
2580          * and connect to the IPC$ share anonymously
2581          */
2582         if (!chan) {
2583                 fstring unix_printer;
2584
2585                 /* the +2 is to strip the leading 2 backslashs */
2586                 fstrcpy(unix_printer, printer + 2);
2587
2588                 chan = talloc_zero(back_channels, struct notify_back_channel);
2589                 if (!chan) {
2590                         return false;
2591                 }
2592                 chan->client_address = *client_ss;
2593
2594                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2595                         TALLOC_FREE(chan);
2596                         return false;
2597                 }
2598                 chan->binding_handle = chan->cli_pipe->binding_handle;
2599
2600                 DLIST_ADD(back_channels, chan);
2601
2602                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2603                                    receive_notify2_message_list);
2604                 /* Tell the connections db we're now interested in printer
2605                  * notify messages. */
2606                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2607                                             true, FLAG_MSG_PRINT_NOTIFY);
2608         }
2609
2610         /*
2611          * Tell the specific printing tdb we want messages for this printer
2612          * by registering our PID.
2613          */
2614
2615         if (!print_notify_register_pid(snum)) {
2616                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2617                           printer));
2618         }
2619
2620         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2621                                                  talloc_tos(),
2622                                                  printer,
2623                                                  localprinter,
2624                                                  type,
2625                                                  0,
2626                                                  NULL,
2627                                                  handle,
2628                                                  &result);
2629         if (!NT_STATUS_IS_OK(status)) {
2630                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2631                 result = ntstatus_to_werror(status);
2632         } else if (!W_ERROR_IS_OK(result)) {
2633                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2634         }
2635
2636         chan->active_connections++;
2637         *_chan = chan;
2638
2639         return (W_ERROR_IS_OK(result));
2640 }
2641
2642 /****************************************************************
2643  ****************************************************************/
2644
2645 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2646                                                              const struct spoolss_NotifyOption *r)
2647 {
2648         struct spoolss_NotifyOption *option;
2649         uint32_t i,k;
2650
2651         if (!r) {
2652                 return NULL;
2653         }
2654
2655         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2656         if (!option) {
2657                 return NULL;
2658         }
2659
2660         *option = *r;
2661
2662         if (!option->count) {
2663                 return option;
2664         }
2665
2666         option->types = talloc_zero_array(option,
2667                 struct spoolss_NotifyOptionType, option->count);
2668         if (!option->types) {
2669                 talloc_free(option);
2670                 return NULL;
2671         }
2672
2673         for (i=0; i < option->count; i++) {
2674                 option->types[i] = r->types[i];
2675
2676                 if (option->types[i].count) {
2677                         option->types[i].fields = talloc_zero_array(option,
2678                                 union spoolss_Field, option->types[i].count);
2679                         if (!option->types[i].fields) {
2680                                 talloc_free(option);
2681                                 return NULL;
2682                         }
2683                         for (k=0; k<option->types[i].count; k++) {
2684                                 option->types[i].fields[k] =
2685                                         r->types[i].fields[k];
2686                         }
2687                 }
2688         }
2689
2690         return option;
2691 }
2692
2693 /****************************************************************
2694  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2695  *
2696  * before replying OK: status=0 a rpc call is made to the workstation
2697  * asking ReplyOpenPrinter
2698  *
2699  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2700  * called from api_spoolss_rffpcnex
2701 ****************************************************************/
2702
2703 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2704                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2705 {
2706         int snum = -1;
2707         struct spoolss_NotifyOption *option = r->in.notify_options;
2708         struct sockaddr_storage client_ss;
2709
2710         /* store the notify value in the printer struct */
2711
2712         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2713
2714         if (!Printer) {
2715                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2716                         "Invalid handle (%s:%u:%u).\n",
2717                         OUR_HANDLE(r->in.handle)));
2718                 return WERR_BADFID;
2719         }
2720
2721         Printer->notify.flags           = r->in.flags;
2722         Printer->notify.options         = r->in.options;
2723         Printer->notify.printerlocal    = r->in.printer_local;
2724         Printer->notify.msg_ctx         = p->msg_ctx;
2725
2726         TALLOC_FREE(Printer->notify.option);
2727         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2728
2729         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2730
2731         /* Connect to the client machine and send a ReplyOpenPrinter */
2732
2733         if ( Printer->printer_type == SPLHND_SERVER)
2734                 snum = -1;
2735         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2736                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2737                 return WERR_BADFID;
2738
2739         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2740                 "client_address is %s\n", p->client_id->addr));
2741
2742         if (!lp_print_notify_backchannel(snum)) {
2743                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2744                         "backchannel disabled\n"));
2745                 return WERR_SERVER_UNAVAILABLE;
2746         }
2747
2748         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2749                                    AI_NUMERICHOST)) {
2750                 return WERR_SERVER_UNAVAILABLE;
2751         }
2752
2753         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2754                                         Printer->notify.printerlocal, REG_SZ,
2755                                         &Printer->notify.cli_hnd,
2756                                         &Printer->notify.cli_chan,
2757                                         &client_ss, p->msg_ctx)) {
2758                 return WERR_SERVER_UNAVAILABLE;
2759         }
2760
2761         return WERR_OK;
2762 }
2763
2764 /*******************************************************************
2765  * fill a notify_info_data with the servername
2766  ********************************************************************/
2767
2768 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2769                                        int snum,
2770                                        struct spoolss_Notify *data,
2771                                        print_queue_struct *queue,
2772                                        struct spoolss_PrinterInfo2 *pinfo2,
2773                                        TALLOC_CTX *mem_ctx)
2774 {
2775         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2776 }
2777
2778 /*******************************************************************
2779  * fill a notify_info_data with the printername (not including the servername).
2780  ********************************************************************/
2781
2782 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2783                                         int snum,
2784                                         struct spoolss_Notify *data,
2785                                         print_queue_struct *queue,
2786                                         struct spoolss_PrinterInfo2 *pinfo2,
2787                                         TALLOC_CTX *mem_ctx)
2788 {
2789         /* the notify name should not contain the \\server\ part */
2790         const char *p = strrchr(pinfo2->printername, '\\');
2791
2792         if (!p) {
2793                 p = pinfo2->printername;
2794         } else {
2795                 p++;
2796         }
2797
2798         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2799 }
2800
2801 /*******************************************************************
2802  * fill a notify_info_data with the servicename
2803  ********************************************************************/
2804
2805 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2806                                       int snum,
2807                                       struct spoolss_Notify *data,
2808                                       print_queue_struct *queue,
2809                                       struct spoolss_PrinterInfo2 *pinfo2,
2810                                       TALLOC_CTX *mem_ctx)
2811 {
2812         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2813 }
2814
2815 /*******************************************************************
2816  * fill a notify_info_data with the port name
2817  ********************************************************************/
2818
2819 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2820                                      int snum,
2821                                      struct spoolss_Notify *data,
2822                                      print_queue_struct *queue,
2823                                      struct spoolss_PrinterInfo2 *pinfo2,
2824                                      TALLOC_CTX *mem_ctx)
2825 {
2826         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2827 }
2828
2829 /*******************************************************************
2830  * fill a notify_info_data with the printername
2831  * but it doesn't exist, have to see what to do
2832  ********************************************************************/
2833
2834 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2835                                        int snum,
2836                                        struct spoolss_Notify *data,
2837                                        print_queue_struct *queue,
2838                                        struct spoolss_PrinterInfo2 *pinfo2,
2839                                        TALLOC_CTX *mem_ctx)
2840 {
2841         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2842 }
2843
2844 /*******************************************************************
2845  * fill a notify_info_data with the comment
2846  ********************************************************************/
2847
2848 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2849                                    int snum,
2850                                    struct spoolss_Notify *data,
2851                                    print_queue_struct *queue,
2852                                    struct spoolss_PrinterInfo2 *pinfo2,
2853                                    TALLOC_CTX *mem_ctx)
2854 {
2855         const char *p;
2856
2857         if (*pinfo2->comment == '\0') {
2858                 p = lp_comment(snum);
2859         } else {
2860                 p = pinfo2->comment;
2861         }
2862
2863         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2864 }
2865
2866 /*******************************************************************
2867  * fill a notify_info_data with the comment
2868  * location = "Room 1, floor 2, building 3"
2869  ********************************************************************/
2870
2871 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2872                                     int snum,
2873                                     struct spoolss_Notify *data,
2874                                     print_queue_struct *queue,
2875                                     struct spoolss_PrinterInfo2 *pinfo2,
2876                                     TALLOC_CTX *mem_ctx)
2877 {
2878         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2879 }
2880
2881 /*******************************************************************
2882  * fill a notify_info_data with the device mode
2883  * jfm:xxxx don't to it for know but that's a real problem !!!
2884  ********************************************************************/
2885
2886 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2887                                    int snum,
2888                                    struct spoolss_Notify *data,
2889                                    print_queue_struct *queue,
2890                                    struct spoolss_PrinterInfo2 *pinfo2,
2891                                    TALLOC_CTX *mem_ctx)
2892 {
2893         /* for a dummy implementation we have to zero the fields */
2894         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2895 }
2896
2897 /*******************************************************************
2898  * fill a notify_info_data with the separator file name
2899  ********************************************************************/
2900
2901 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2902                                    int snum,
2903                                    struct spoolss_Notify *data,
2904                                    print_queue_struct *queue,
2905                                    struct spoolss_PrinterInfo2 *pinfo2,
2906                                    TALLOC_CTX *mem_ctx)
2907 {
2908         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2909 }
2910
2911 /*******************************************************************
2912  * fill a notify_info_data with the print processor
2913  * jfm:xxxx return always winprint to indicate we don't do anything to it
2914  ********************************************************************/
2915
2916 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2917                                            int snum,
2918                                            struct spoolss_Notify *data,
2919                                            print_queue_struct *queue,
2920                                            struct spoolss_PrinterInfo2 *pinfo2,
2921                                            TALLOC_CTX *mem_ctx)
2922 {
2923         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2924 }
2925
2926 /*******************************************************************
2927  * fill a notify_info_data with the print processor options
2928  * jfm:xxxx send an empty string
2929  ********************************************************************/
2930
2931 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2932                                       int snum,
2933                                       struct spoolss_Notify *data,
2934                                       print_queue_struct *queue,
2935                                       struct spoolss_PrinterInfo2 *pinfo2,
2936                                       TALLOC_CTX *mem_ctx)
2937 {
2938         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2939 }
2940
2941 /*******************************************************************
2942  * fill a notify_info_data with the data type
2943  * jfm:xxxx always send RAW as data type
2944  ********************************************************************/
2945
2946 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2947                                     int snum,
2948                                     struct spoolss_Notify *data,
2949                                     print_queue_struct *queue,
2950                                     struct spoolss_PrinterInfo2 *pinfo2,
2951                                     TALLOC_CTX *mem_ctx)
2952 {
2953         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2954 }
2955
2956 /*******************************************************************
2957  * fill a notify_info_data with the security descriptor
2958  * jfm:xxxx send an null pointer to say no security desc
2959  * have to implement security before !
2960  ********************************************************************/
2961
2962 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2963                                          int snum,
2964                                          struct spoolss_Notify *data,
2965                                          print_queue_struct *queue,
2966                                          struct spoolss_PrinterInfo2 *pinfo2,
2967                                          TALLOC_CTX *mem_ctx)
2968 {
2969         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2970 }
2971
2972 /*******************************************************************
2973  * fill a notify_info_data with the attributes
2974  * jfm:xxxx a samba printer is always shared
2975  ********************************************************************/
2976
2977 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2978                                       int snum,
2979                                       struct spoolss_Notify *data,
2980                                       print_queue_struct *queue,
2981                                       struct spoolss_PrinterInfo2 *pinfo2,
2982                                       TALLOC_CTX *mem_ctx)
2983 {
2984         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2985 }
2986
2987 /*******************************************************************
2988  * fill a notify_info_data with the priority
2989  ********************************************************************/
2990
2991 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2992                                     int snum,
2993                                     struct spoolss_Notify *data,
2994                                     print_queue_struct *queue,
2995                                     struct spoolss_PrinterInfo2 *pinfo2,
2996                                     TALLOC_CTX *mem_ctx)
2997 {
2998         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2999 }
3000
3001 /*******************************************************************
3002  * fill a notify_info_data with the default priority
3003  ********************************************************************/
3004
3005 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3006                                             int snum,
3007                                             struct spoolss_Notify *data,
3008                                             print_queue_struct *queue,
3009                                             struct spoolss_PrinterInfo2 *pinfo2,
3010                                             TALLOC_CTX *mem_ctx)
3011 {
3012         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3013 }
3014
3015 /*******************************************************************
3016  * fill a notify_info_data with the start time
3017  ********************************************************************/
3018
3019 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3020                                       int snum,
3021                                       struct spoolss_Notify *data,
3022                                       print_queue_struct *queue,
3023                                       struct spoolss_PrinterInfo2 *pinfo2,
3024                                       TALLOC_CTX *mem_ctx)
3025 {
3026         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3027 }
3028
3029 /*******************************************************************
3030  * fill a notify_info_data with the until time
3031  ********************************************************************/
3032
3033 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3034                                       int snum,
3035                                       struct spoolss_Notify *data,
3036                                       print_queue_struct *queue,
3037                                       struct spoolss_PrinterInfo2 *pinfo2,
3038                                       TALLOC_CTX *mem_ctx)
3039 {
3040         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3041 }
3042
3043 /*******************************************************************
3044  * fill a notify_info_data with the status
3045  ********************************************************************/
3046
3047 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3048                                   int snum,
3049                                   struct spoolss_Notify *data,
3050                                   print_queue_struct *queue,
3051                                   struct spoolss_PrinterInfo2 *pinfo2,
3052                                   TALLOC_CTX *mem_ctx)
3053 {
3054         print_status_struct status;
3055
3056         print_queue_length(msg_ctx, snum, &status);
3057         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3058 }
3059
3060 /*******************************************************************
3061  * fill a notify_info_data with the number of jobs queued
3062  ********************************************************************/
3063
3064 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3065                                  int snum,
3066                                  struct spoolss_Notify *data,
3067                                  print_queue_struct *queue,
3068                                  struct spoolss_PrinterInfo2 *pinfo2,
3069                                  TALLOC_CTX *mem_ctx)
3070 {
3071         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3072                 data, print_queue_length(msg_ctx, snum, NULL));
3073 }
3074
3075 /*******************************************************************
3076  * fill a notify_info_data with the average ppm
3077  ********************************************************************/
3078
3079 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3080                                        int snum,
3081                                        struct spoolss_Notify *data,
3082                                        print_queue_struct *queue,
3083                                        struct spoolss_PrinterInfo2 *pinfo2,
3084                                        TALLOC_CTX *mem_ctx)
3085 {
3086         /* always respond 8 pages per minutes */
3087         /* a little hard ! */
3088         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3089 }
3090
3091 /*******************************************************************
3092  * fill a notify_info_data with username
3093  ********************************************************************/
3094
3095 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3096                                     int snum,
3097                                     struct spoolss_Notify *data,
3098                                     print_queue_struct *queue,
3099                                     struct spoolss_PrinterInfo2 *pinfo2,
3100                                     TALLOC_CTX *mem_ctx)
3101 {
3102         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3103 }
3104
3105 /*******************************************************************
3106  * fill a notify_info_data with job status
3107  ********************************************************************/
3108
3109 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3110                                       int snum,
3111                                       struct spoolss_Notify *data,
3112                                       print_queue_struct *queue,
3113                                       struct spoolss_PrinterInfo2 *pinfo2,
3114                                       TALLOC_CTX *mem_ctx)
3115 {
3116         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3117 }
3118
3119 /*******************************************************************
3120  * fill a notify_info_data with job name
3121  ********************************************************************/
3122
3123 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3124                                     int snum,
3125                                     struct spoolss_Notify *data,
3126                                     print_queue_struct *queue,
3127                                     struct spoolss_PrinterInfo2 *pinfo2,
3128                                     TALLOC_CTX *mem_ctx)
3129 {
3130         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3131 }
3132
3133 /*******************************************************************
3134  * fill a notify_info_data with job status
3135  ********************************************************************/
3136
3137 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3138                                              int snum,
3139                                              struct spoolss_Notify *data,
3140                                              print_queue_struct *queue,
3141                                              struct spoolss_PrinterInfo2 *pinfo2,
3142                                              TALLOC_CTX *mem_ctx)
3143 {
3144         /*
3145          * Now we're returning job status codes we just return a "" here. JRA.
3146          */
3147
3148         const char *p = "";
3149
3150 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3151         p = "unknown";
3152
3153         switch (queue->status) {
3154         case LPQ_QUEUED:
3155                 p = "Queued";
3156                 break;
3157         case LPQ_PAUSED:
3158                 p = "";    /* NT provides the paused string */
3159                 break;
3160         case LPQ_SPOOLING:
3161                 p = "Spooling";
3162                 break;
3163         case LPQ_PRINTING:
3164                 p = "Printing";
3165                 break;
3166         }
3167 #endif /* NO LONGER NEEDED. */
3168
3169         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3170 }
3171
3172 /*******************************************************************
3173  * fill a notify_info_data with job time
3174  ********************************************************************/
3175
3176 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3177                                     int snum,
3178                                     struct spoolss_Notify *data,
3179                                     print_queue_struct *queue,
3180                                     struct spoolss_PrinterInfo2 *pinfo2,
3181                                     TALLOC_CTX *mem_ctx)
3182 {
3183         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3184 }
3185
3186 /*******************************************************************
3187  * fill a notify_info_data with job size
3188  ********************************************************************/
3189
3190 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3191                                     int snum,
3192                                     struct spoolss_Notify *data,
3193                                     print_queue_struct *queue,
3194                                     struct spoolss_PrinterInfo2 *pinfo2,
3195                                     TALLOC_CTX *mem_ctx)
3196 {
3197         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3198 }
3199
3200 /*******************************************************************
3201  * fill a notify_info_data with page info
3202  ********************************************************************/
3203 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3204                                        int snum,
3205                                 struct spoolss_Notify *data,
3206                                 print_queue_struct *queue,
3207                                 struct spoolss_PrinterInfo2 *pinfo2,
3208                                 TALLOC_CTX *mem_ctx)
3209 {
3210         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3211 }
3212
3213 /*******************************************************************
3214  * fill a notify_info_data with pages printed info.
3215  ********************************************************************/
3216 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3217                                          int snum,
3218                                 struct spoolss_Notify *data,
3219                                 print_queue_struct *queue,
3220                                 struct spoolss_PrinterInfo2 *pinfo2,
3221                                 TALLOC_CTX *mem_ctx)
3222 {
3223         /* Add code when back-end tracks this */
3224         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3225 }
3226
3227 /*******************************************************************
3228  Fill a notify_info_data with job position.
3229  ********************************************************************/
3230
3231 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3232                                         int snum,
3233                                         struct spoolss_Notify *data,
3234                                         print_queue_struct *queue,
3235                                         struct spoolss_PrinterInfo2 *pinfo2,
3236                                         TALLOC_CTX *mem_ctx)
3237 {
3238         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3239 }
3240
3241 /*******************************************************************
3242  Fill a notify_info_data with submitted time.
3243  ********************************************************************/
3244
3245 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3246                                           int snum,
3247                                           struct spoolss_Notify *data,
3248                                           print_queue_struct *queue,
3249                                           struct spoolss_PrinterInfo2 *pinfo2,
3250                                           TALLOC_CTX *mem_ctx)
3251 {
3252         data->data.string.string = NULL;
3253         data->data.string.size = 0;
3254
3255         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3256                                &data->data.string.string,
3257                                &data->data.string.size);
3258
3259 }
3260
3261 struct s_notify_info_data_table
3262 {
3263         enum spoolss_NotifyType type;
3264         uint16_t field;
3265         const char *name;
3266         enum spoolss_NotifyTable variable_type;
3267         void (*fn) (struct messaging_context *msg_ctx,
3268                     int snum, struct spoolss_Notify *data,
3269                     print_queue_struct *queue,
3270                     struct spoolss_PrinterInfo2 *pinfo2,
3271                     TALLOC_CTX *mem_ctx);
3272 };
3273
3274 /* A table describing the various print notification constants and
3275    whether the notification data is a pointer to a variable sized
3276    buffer, a one value uint32_t or a two value uint32_t. */
3277
3278 static const struct s_notify_info_data_table notify_info_data_table[] =
3279 {
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3306 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3316 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3317 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3318 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3319 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3320 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3321 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3322 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3323 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3324 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3325 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3326 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3327 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3328 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3329 };
3330
3331 /*******************************************************************
3332  Return the variable_type of info_data structure.
3333 ********************************************************************/
3334
3335 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3336                                                                   uint16_t field)
3337 {
3338         int i=0;
3339
3340         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3341                 if ( (notify_info_data_table[i].type == type) &&
3342                      (notify_info_data_table[i].field == field) ) {
3343                         return notify_info_data_table[i].variable_type;
3344                 }
3345         }
3346
3347         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3348
3349         return (enum spoolss_NotifyTable) 0;
3350 }
3351
3352 /****************************************************************************
3353 ****************************************************************************/
3354
3355 static bool search_notify(enum spoolss_NotifyType type,
3356                           uint16_t field,
3357                           int *value)
3358 {
3359         int i;
3360
3361         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3362                 if (notify_info_data_table[i].type == type &&
3363                     notify_info_data_table[i].field == field &&
3364                     notify_info_data_table[i].fn != NULL) {
3365                         *value = i;
3366                         return true;
3367                 }
3368         }
3369
3370         return false;
3371 }
3372
3373 /****************************************************************************
3374 ****************************************************************************/
3375
3376 static void construct_info_data(struct spoolss_Notify *info_data,
3377                                 enum spoolss_NotifyType type,
3378                                 uint16_t field, int id)
3379 {
3380         info_data->type                 = type;
3381         info_data->field.field          = field;
3382         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3383         info_data->job_id               = id;
3384 }
3385
3386 /*******************************************************************
3387  *
3388  * fill a notify_info struct with info asked
3389  *
3390  ********************************************************************/
3391
3392 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3393                                           struct printer_handle *print_hnd,
3394                                           struct spoolss_NotifyInfo *info,
3395                                           struct spoolss_PrinterInfo2 *pinfo2,
3396                                           int snum,
3397                                           const struct spoolss_NotifyOptionType *option_type,
3398                                           uint32_t id,
3399                                           TALLOC_CTX *mem_ctx)
3400 {
3401         int field_num,j;
3402         enum spoolss_NotifyType type;
3403         uint16_t field;
3404
3405         struct spoolss_Notify *current_data;
3406         print_queue_struct *queue=NULL;
3407
3408         type = option_type->type;
3409
3410         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3411                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3412                 option_type->count, lp_servicename(snum)));
3413
3414         for(field_num=0; field_num < option_type->count; field_num++) {
3415                 field = option_type->fields[field_num].field;
3416
3417                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3418
3419                 if (!search_notify(type, field, &j) )
3420                         continue;
3421
3422                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3423                                                       struct spoolss_Notify,
3424                                                       info->count + 1);
3425                 if (info->notifies == NULL) {
3426                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3427                         return false;
3428                 }
3429
3430                 current_data = &info->notifies[info->count];
3431
3432                 construct_info_data(current_data, type, field, id);
3433
3434                 DEBUG(10, ("construct_notify_printer_info: "
3435                            "calling [%s]  snum=%d  printername=[%s])\n",
3436                            notify_info_data_table[j].name, snum,
3437                            pinfo2->printername));
3438
3439                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3440                                              queue, pinfo2, mem_ctx);
3441
3442                 info->count++;
3443         }
3444
3445         return true;
3446 }
3447
3448 /*******************************************************************
3449  *
3450  * fill a notify_info struct with info asked
3451  *
3452  ********************************************************************/
3453
3454 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3455                                        print_queue_struct *queue,
3456                                        struct spoolss_NotifyInfo *info,
3457                                        struct spoolss_PrinterInfo2 *pinfo2,
3458                                        int snum,
3459                                        const struct spoolss_NotifyOptionType *option_type,
3460                                        uint32_t id,
3461                                        TALLOC_CTX *mem_ctx)
3462 {
3463         int field_num,j;
3464         enum spoolss_NotifyType type;
3465         uint16_t field;
3466         struct spoolss_Notify *current_data;
3467
3468         DEBUG(4,("construct_notify_jobs_info\n"));
3469
3470         type = option_type->type;
3471
3472         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3473                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3474                 option_type->count));
3475
3476         for(field_num=0; field_num<option_type->count; field_num++) {
3477                 field = option_type->fields[field_num].field;
3478
3479                 if (!search_notify(type, field, &j) )
3480                         continue;
3481
3482                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3483                                                       struct spoolss_Notify,
3484                                                       info->count + 1);
3485                 if (info->notifies == NULL) {
3486                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3487                         return false;
3488                 }
3489
3490                 current_data=&(info->notifies[info->count]);
3491
3492                 construct_info_data(current_data, type, field, id);
3493                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3494                                              queue, pinfo2, mem_ctx);
3495                 info->count++;
3496         }
3497
3498         return true;
3499 }
3500
3501 /*
3502  * JFM: The enumeration is not that simple, it's even non obvious.
3503  *
3504  * let's take an example: I want to monitor the PRINTER SERVER for
3505  * the printer's name and the number of jobs currently queued.
3506  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3507  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3508  *
3509  * I have 3 printers on the back of my server.
3510  *
3511  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3512  * structures.
3513  *   Number     Data                    Id
3514  *      1       printer 1 name          1
3515  *      2       printer 1 cjob          1
3516  *      3       printer 2 name          2
3517  *      4       printer 2 cjob          2
3518  *      5       printer 3 name          3
3519  *      6       printer 3 name          3
3520  *
3521  * that's the print server case, the printer case is even worse.
3522  */
3523
3524 /*******************************************************************
3525  *
3526  * enumerate all printers on the printserver
3527  * fill a notify_info struct with info asked
3528  *
3529  ********************************************************************/
3530
3531 static WERROR printserver_notify_info(struct pipes_struct *p,
3532                                       struct policy_handle *hnd,
3533                                       struct spoolss_NotifyInfo *info,
3534                                       TALLOC_CTX *mem_ctx)
3535 {
3536         int snum;
3537         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3538         int n_services=lp_numservices();
3539         int i;
3540         struct spoolss_NotifyOption *option;
3541         struct spoolss_NotifyOptionType option_type;
3542         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3543         WERROR result;
3544
3545         DEBUG(4,("printserver_notify_info\n"));
3546
3547         if (!Printer)
3548                 return WERR_BADFID;
3549
3550         option = Printer->notify.option;
3551
3552         info->version   = 2;
3553         info->notifies  = NULL;
3554         info->count     = 0;
3555
3556         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3557            sending a ffpcn() request first */
3558
3559         if ( !option )
3560                 return WERR_BADFID;
3561
3562         for (i=0; i<option->count; i++) {
3563                 option_type = option->types[i];
3564
3565                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3566                         continue;
3567
3568                 for (snum = 0; snum < n_services; snum++) {
3569                         if (!lp_browseable(snum) ||
3570                             !lp_snum_ok(snum) ||
3571                             !lp_print_ok(snum)) {
3572                                 continue; /* skip */
3573                         }
3574
3575                         /* Maybe we should use the SYSTEM session_info here... */
3576                         result = winreg_get_printer(mem_ctx,
3577                                                     get_session_info_system(),
3578                                                     p->msg_ctx,
3579                                                     lp_servicename(snum),
3580                                                     &pinfo2);
3581                         if (!W_ERROR_IS_OK(result)) {
3582                                 DEBUG(4, ("printserver_notify_info: "
3583                                           "Failed to get printer [%s]\n",
3584                                           lp_servicename(snum)));
3585                                 continue;
3586                         }
3587
3588
3589                         construct_notify_printer_info(p->msg_ctx,
3590                                                       Printer, info,
3591                                                       pinfo2, snum,
3592                                                       &option_type, snum,
3593                                                       mem_ctx);
3594
3595                         TALLOC_FREE(pinfo2);
3596                 }
3597         }
3598
3599 #if 0
3600         /*
3601          * Debugging information, don't delete.
3602          */
3603
3604         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3605         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3606         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3607
3608         for (i=0; i<info->count; i++) {
3609                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3610                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3611                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3612         }
3613 #endif
3614
3615         return WERR_OK;
3616 }
3617
3618 /*******************************************************************
3619  *
3620  * fill a notify_info struct with info asked
3621  *
3622  ********************************************************************/
3623
3624 static WERROR printer_notify_info(struct pipes_struct *p,
3625                                   struct policy_handle *hnd,
3626                                   struct spoolss_NotifyInfo *info,
3627                                   TALLOC_CTX *mem_ctx)
3628 {
3629         int snum;
3630         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3631         int i;
3632         uint32_t id;
3633         struct spoolss_NotifyOption *option;
3634         struct spoolss_NotifyOptionType option_type;
3635         int count,j;
3636         print_queue_struct *queue=NULL;
3637         print_status_struct status;
3638         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3639         WERROR result;
3640
3641         DEBUG(4,("printer_notify_info\n"));
3642
3643         if (!Printer)
3644                 return WERR_BADFID;
3645
3646         option = Printer->notify.option;
3647         id = 0x0;
3648
3649         info->version   = 2;
3650         info->notifies  = NULL;
3651         info->count     = 0;
3652
3653         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3654            sending a ffpcn() request first */
3655
3656         if ( !option )
3657                 return WERR_BADFID;
3658
3659         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3660                 return WERR_BADFID;
3661         }
3662
3663         /* Maybe we should use the SYSTEM session_info here... */
3664         result = winreg_get_printer(mem_ctx,
3665                                     get_session_info_system(),
3666                                     p->msg_ctx,
3667                                     lp_servicename(snum), &pinfo2);
3668         if (!W_ERROR_IS_OK(result)) {
3669                 return WERR_BADFID;
3670         }
3671
3672         for (i=0; i<option->count; i++) {
3673                 option_type = option->types[i];
3674
3675                 switch (option_type.type) {
3676                 case PRINTER_NOTIFY_TYPE:
3677                         if (construct_notify_printer_info(p->msg_ctx,
3678                                                           Printer, info,
3679                                                           pinfo2, snum,
3680                                                           &option_type, id,
3681                                                           mem_ctx)) {
3682                                 id--;
3683                         }
3684                         break;
3685
3686                 case JOB_NOTIFY_TYPE:
3687
3688                         count = print_queue_status(p->msg_ctx, snum, &queue,
3689                                                    &status);
3690
3691                         for (j=0; j<count; j++) {
3692                                 construct_notify_jobs_info(p->msg_ctx,
3693                                                            &queue[j], info,
3694                                                            pinfo2, snum,
3695                                                            &option_type,
3696                                                            queue[j].job,
3697                                                            mem_ctx);
3698                         }
3699
3700                         SAFE_FREE(queue);
3701                         break;
3702                 }
3703         }
3704
3705         /*
3706          * Debugging information, don't delete.
3707          */
3708         /*
3709         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3710         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3711         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3712
3713         for (i=0; i<info->count; i++) {
3714                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3715                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3716                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3717         }
3718         */
3719
3720         talloc_free(pinfo2);
3721         return WERR_OK;
3722 }
3723
3724 /****************************************************************
3725  _spoolss_RouterRefreshPrinterChangeNotify
3726 ****************************************************************/
3727
3728 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3729                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3730 {
3731         struct spoolss_NotifyInfo *info;
3732
3733         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3734         WERROR result = WERR_BADFID;
3735
3736         /* we always have a spoolss_NotifyInfo struct */
3737         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3738         if (!info) {
3739                 result = WERR_NOMEM;
3740                 goto done;
3741         }
3742
3743         *r->out.info = info;
3744
3745         if (!Printer) {
3746                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3747                         "Invalid handle (%s:%u:%u).\n",
3748                         OUR_HANDLE(r->in.handle)));
3749                 goto done;
3750         }
3751
3752         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3753
3754         /*
3755          *      We are now using the change value, and
3756          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3757          *      I don't have a global notification system, I'm sending back all the
3758          *      information even when _NOTHING_ has changed.
3759          */
3760
3761         /* We need to keep track of the change value to send back in
3762            RRPCN replies otherwise our updates are ignored. */
3763
3764         Printer->notify.fnpcn = true;
3765
3766         if (Printer->notify.cli_chan != NULL &&
3767             Printer->notify.cli_chan->active_connections > 0) {
3768                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3769                         "Saving change value in request [%x]\n",
3770                         r->in.change_low));
3771                 Printer->notify.change = r->in.change_low;
3772         }
3773
3774         /* just ignore the spoolss_NotifyOption */
3775
3776         switch (Printer->printer_type) {
3777                 case SPLHND_SERVER:
3778                         result = printserver_notify_info(p, r->in.handle,
3779                                                          info, p->mem_ctx);
3780                         break;
3781
3782                 case SPLHND_PRINTER:
3783                         result = printer_notify_info(p, r->in.handle,
3784                                                      info, p->mem_ctx);
3785                         break;
3786         }
3787
3788         Printer->notify.fnpcn = false;
3789
3790 done:
3791         return result;
3792 }
3793
3794 /********************************************************************
3795  ********************************************************************/
3796
3797 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3798                                  const char *servername,
3799                                  const char *printername,
3800                                  const char **printername_p)
3801 {
3802         /* FIXME: add lp_force_printername() */
3803
3804         if (servername == NULL) {
3805                 *printername_p = talloc_strdup(mem_ctx, printername);
3806                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3807                 return WERR_OK;
3808         }
3809
3810         if (servername[0] == '\\' && servername[1] == '\\') {
3811                 servername += 2;
3812         }
3813
3814         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3815         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3816
3817         return WERR_OK;
3818 }
3819
3820 /********************************************************************
3821  ********************************************************************/
3822
3823 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3824                                           const char *printername)
3825 {
3826         if (dm == NULL) {
3827                 return;
3828         }
3829
3830         dm->devicename = talloc_strndup(dm, printername,
3831                                         MIN(strlen(printername), 31));
3832 }
3833
3834 /********************************************************************
3835  * construct_printer_info_0
3836  * fill a printer_info_0 struct
3837  ********************************************************************/
3838
3839 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3840                                       const struct auth_serversupplied_info *session_info,
3841                                       struct messaging_context *msg_ctx,
3842                                       struct spoolss_PrinterInfo2 *info2,
3843                                       const char *servername,
3844                                       struct spoolss_PrinterInfo0 *r,
3845                                       int snum)
3846 {
3847         int count;
3848         struct printer_session_counter *session_counter;
3849         struct timeval setuptime;
3850         print_status_struct status;
3851         WERROR result;
3852
3853         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3854         if (!W_ERROR_IS_OK(result)) {
3855                 return result;
3856         }
3857
3858         if (servername) {
3859                 r->servername = talloc_strdup(mem_ctx, servername);
3860                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3861         } else {
3862                 r->servername = NULL;
3863         }
3864
3865         count = print_queue_length(msg_ctx, snum, &status);
3866
3867         /* check if we already have a counter for this printer */
3868         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3869                 if (session_counter->snum == snum)
3870                         break;
3871         }
3872
3873         /* it's the first time, add it to the list */
3874         if (session_counter == NULL) {
3875                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3876                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3877                 session_counter->snum           = snum;
3878                 session_counter->counter        = 0;
3879                 DLIST_ADD(counter_list, session_counter);
3880         }
3881
3882         /* increment it */
3883         session_counter->counter++;
3884
3885         r->cjobs                        = count;
3886         r->total_jobs                   = 0;
3887         r->total_bytes                  = 0;
3888
3889         get_startup_time(&setuptime);
3890         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3891
3892         /* JFM:
3893          * the global_counter should be stored in a TDB as it's common to all the clients
3894          * and should be zeroed on samba startup
3895          */
3896         r->global_counter               = session_counter->counter;
3897         r->total_pages                  = 0;
3898         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3899         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3900         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3901         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3902         r->spooling                     = 0;
3903         r->max_spooling                 = 0;
3904         r->session_counter              = session_counter->counter;
3905         r->num_error_out_of_paper       = 0x0;
3906         r->num_error_not_ready          = 0x0;          /* number of print failure */
3907         r->job_error                    = 0x0;
3908         r->number_of_processors         = 0x1;
3909         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3910         r->high_part_total_bytes        = 0x0;
3911
3912         /* ChangeID in milliseconds*/
3913         winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3914                                     info2->sharename, &r->change_id);
3915
3916         r->last_error                   = WERR_OK;
3917         r->status                       = nt_printq_status(status.status);
3918         r->enumerate_network_printers   = 0x0;
3919         r->c_setprinter                 = 0x0;
3920         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3921         r->processor_level              = 0x6;          /* 6  ???*/
3922         r->ref_ic                       = 0;
3923         r->reserved2                    = 0;
3924         r->reserved3                    = 0;
3925
3926         return WERR_OK;
3927 }
3928
3929
3930 /********************************************************************
3931  * construct_printer_info1
3932  * fill a spoolss_PrinterInfo1 struct
3933 ********************************************************************/
3934
3935 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3936                                       const struct spoolss_PrinterInfo2 *info2,
3937                                       uint32_t flags,
3938                                       const char *servername,
3939                                       struct spoolss_PrinterInfo1 *r,
3940                                       int snum)
3941 {
3942         WERROR result;
3943
3944         r->flags                = flags;
3945
3946         if (info2->comment == NULL || info2->comment[0] == '\0') {
3947                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3948         } else {
3949                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3950         }
3951         W_ERROR_HAVE_NO_MEMORY(r->comment);
3952
3953         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3954         if (!W_ERROR_IS_OK(result)) {
3955                 return result;
3956         }
3957
3958         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3959                                                   r->name,
3960                                                   info2->drivername,
3961                                                   r->comment);
3962         W_ERROR_HAVE_NO_MEMORY(r->description);
3963
3964         return WERR_OK;
3965 }
3966
3967 /********************************************************************
3968  * construct_printer_info2
3969  * fill a spoolss_PrinterInfo2 struct
3970 ********************************************************************/
3971
3972 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3973                                       struct messaging_context *msg_ctx,
3974                                       const struct spoolss_PrinterInfo2 *info2,
3975                                       const char *servername,
3976                                       struct spoolss_PrinterInfo2 *r,
3977                                       int snum)
3978 {
3979         int count;
3980         print_status_struct status;
3981         WERROR result;
3982
3983         count = print_queue_length(msg_ctx, snum, &status);
3984
3985         if (servername) {
3986                 r->servername           = talloc_strdup(mem_ctx, servername);
3987                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3988         } else {
3989                 r->servername           = NULL;
3990         }
3991
3992         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3993         if (!W_ERROR_IS_OK(result)) {
3994                 return result;
3995         }
3996
3997         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3998         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3999         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4000         W_ERROR_HAVE_NO_MEMORY(r->portname);
4001         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4002         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4003
4004         if (info2->comment[0] == '\0') {
4005                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4006         } else {
4007                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4008         }
4009         W_ERROR_HAVE_NO_MEMORY(r->comment);
4010
4011         r->location             = talloc_strdup(mem_ctx, info2->location);
4012         W_ERROR_HAVE_NO_MEMORY(r->location);
4013         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4014         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4015         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4016         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4017         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4018         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4019         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4020         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4021
4022         r->attributes           = info2->attributes;
4023
4024         r->priority             = info2->priority;
4025         r->defaultpriority      = info2->defaultpriority;
4026         r->starttime            = info2->starttime;
4027         r->untiltime            = info2->untiltime;
4028         r->status               = nt_printq_status(status.status);
4029         r->cjobs                = count;
4030         r->averageppm           = info2->averageppm;
4031
4032         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4033         if (!r->devmode) {
4034                 DEBUG(8,("Returning NULL Devicemode!\n"));
4035         }
4036
4037         compose_devicemode_devicename(r->devmode, r->printername);
4038
4039         r->secdesc = NULL;
4040
4041         if (info2->secdesc != NULL) {
4042                 /* don't use talloc_steal() here unless you do a deep steal of all
4043                    the SEC_DESC members */
4044
4045                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4046         }
4047
4048         return WERR_OK;
4049 }
4050
4051 /********************************************************************
4052  * construct_printer_info3
4053  * fill a spoolss_PrinterInfo3 struct
4054  ********************************************************************/
4055
4056 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4057                                       const struct spoolss_PrinterInfo2 *info2,
4058                                       const char *servername,
4059                                       struct spoolss_PrinterInfo3 *r,
4060                                       int snum)
4061 {
4062         /* These are the components of the SD we are returning. */
4063
4064         if (info2->secdesc != NULL) {
4065                 /* don't use talloc_steal() here unless you do a deep steal of all
4066                    the SEC_DESC members */
4067
4068                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4069                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4070         }
4071
4072         return WERR_OK;
4073 }
4074
4075 /********************************************************************
4076  * construct_printer_info4
4077  * fill a spoolss_PrinterInfo4 struct
4078  ********************************************************************/
4079
4080 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4081                                       const struct spoolss_PrinterInfo2 *info2,
4082                                       const char *servername,
4083                                       struct spoolss_PrinterInfo4 *r,
4084                                       int snum)
4085 {
4086         WERROR result;
4087
4088         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4089         if (!W_ERROR_IS_OK(result)) {
4090                 return result;
4091         }
4092
4093         if (servername) {
4094                 r->servername   = talloc_strdup(mem_ctx, servername);
4095                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4096         } else {
4097                 r->servername = NULL;
4098         }
4099
4100         r->attributes   = info2->attributes;
4101
4102         return WERR_OK;
4103 }
4104
4105 /********************************************************************
4106  * construct_printer_info5
4107  * fill a spoolss_PrinterInfo5 struct
4108  ********************************************************************/
4109
4110 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4111                                       const struct spoolss_PrinterInfo2 *info2,
4112                                       const char *servername,
4113                                       struct spoolss_PrinterInfo5 *r,
4114                                       int snum)
4115 {
4116         WERROR result;
4117
4118         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4119         if (!W_ERROR_IS_OK(result)) {
4120                 return result;
4121         }
4122
4123         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4124         W_ERROR_HAVE_NO_MEMORY(r->portname);
4125
4126         r->attributes   = info2->attributes;
4127
4128         /* these two are not used by NT+ according to MSDN */
4129         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4130         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4131
4132         return WERR_OK;
4133 }
4134
4135 /********************************************************************
4136  * construct_printer_info_6
4137  * fill a spoolss_PrinterInfo6 struct
4138  ********************************************************************/
4139
4140 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4141                                       struct messaging_context *msg_ctx,
4142                                       const struct spoolss_PrinterInfo2 *info2,
4143                                       const char *servername,
4144                                       struct spoolss_PrinterInfo6 *r,
4145                                       int snum)
4146 {
4147         int count;
4148         print_status_struct status;
4149
4150         count = print_queue_length(msg_ctx, snum, &status);
4151
4152         r->status = nt_printq_status(status.status);
4153
4154         return WERR_OK;
4155 }
4156
4157 /********************************************************************
4158  * construct_printer_info7
4159  * fill a spoolss_PrinterInfo7 struct
4160  ********************************************************************/
4161
4162 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4163                                       struct messaging_context *msg_ctx,
4164                                       const char *servername,
4165                                       struct spoolss_PrinterInfo7 *r,
4166                                       int snum)
4167 {
4168         struct auth_serversupplied_info *session_info;
4169         struct GUID guid;
4170         NTSTATUS status;
4171
4172         status = make_session_info_system(mem_ctx, &session_info);
4173         if (!NT_STATUS_IS_OK(status)) {
4174                 DEBUG(0, ("construct_printer_info7: "
4175                           "Could not create system session_info\n"));
4176                 return WERR_NOMEM;
4177         }
4178
4179         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4180                                  servername,
4181                                  lp_servicename(snum), &guid, NULL)) {
4182                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4183                 r->action = DSPRINT_PUBLISH;
4184         } else {
4185                 r->guid = talloc_strdup(mem_ctx, "");
4186                 r->action = DSPRINT_UNPUBLISH;
4187         }
4188         W_ERROR_HAVE_NO_MEMORY(r->guid);
4189
4190         TALLOC_FREE(session_info);
4191         return WERR_OK;
4192 }
4193
4194 /********************************************************************
4195  * construct_printer_info8
4196  * fill a spoolss_PrinterInfo8 struct
4197  ********************************************************************/
4198
4199 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4200                                       const struct spoolss_PrinterInfo2 *info2,
4201                                       const char *servername,
4202                                       struct spoolss_DeviceModeInfo *r,
4203                                       int snum)
4204 {
4205         WERROR result;
4206         const char *printername;
4207
4208         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4209         if (!W_ERROR_IS_OK(result)) {
4210                 return result;
4211         }
4212
4213         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4214         if (!r->devmode) {
4215                 DEBUG(8,("Returning NULL Devicemode!\n"));
4216         }
4217
4218         compose_devicemode_devicename(r->devmode, printername);
4219
4220         return WERR_OK;
4221 }
4222
4223
4224 /********************************************************************
4225 ********************************************************************/
4226
4227 static bool snum_is_shared_printer(int snum)
4228 {
4229         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4230 }
4231
4232 /********************************************************************
4233  Spoolss_enumprinters.
4234 ********************************************************************/
4235
4236 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4237                                            const struct auth_serversupplied_info *session_info,
4238                                            struct messaging_context *msg_ctx,
4239                                            const char *servername,
4240                                            uint32_t level,
4241                                            uint32_t flags,
4242                                            union spoolss_PrinterInfo **info_p,
4243                                            uint32_t *count_p)
4244 {
4245         int snum;
4246         int n_services = lp_numservices();
4247         union spoolss_PrinterInfo *info = NULL;
4248         uint32_t count = 0;
4249         WERROR result = WERR_OK;
4250
4251         *count_p = 0;
4252         *info_p = NULL;
4253
4254         for (snum = 0; snum < n_services; snum++) {
4255
4256                 const char *printer;
4257                 struct spoolss_PrinterInfo2 *info2;
4258
4259                 if (!snum_is_shared_printer(snum)) {
4260                         continue;
4261                 }
4262
4263                 printer = lp_const_servicename(snum);
4264
4265                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4266                         printer, snum));
4267
4268                 result = winreg_create_printer(mem_ctx,
4269                                                session_info,
4270                                                msg_ctx,
4271                                                printer);
4272                 if (!W_ERROR_IS_OK(result)) {
4273                         goto out;
4274                 }
4275
4276                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4277                                             union spoolss_PrinterInfo,
4278                                             count + 1);
4279                 if (!info) {
4280                         result = WERR_NOMEM;
4281                         goto out;
4282                 }
4283
4284                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4285                                             printer, &info2);
4286                 if (!W_ERROR_IS_OK(result)) {
4287                         goto out;
4288                 }
4289
4290                 switch (level) {
4291                 case 0:
4292                         result = construct_printer_info0(info, session_info,
4293                                                          msg_ctx, info2,
4294                                                          servername,
4295                                                          &info[count].info0, snum);
4296                         break;
4297                 case 1:
4298                         result = construct_printer_info1(info, info2, flags,
4299                                                          servername,
4300                                                          &info[count].info1, snum);
4301                         break;
4302                 case 2:
4303                         result = construct_printer_info2(info, msg_ctx, info2,
4304                                                          servername,
4305                                                          &info[count].info2, snum);
4306                         break;
4307                 case 4:
4308                         result = construct_printer_info4(info, info2,
4309                                                          servername,
4310                                                          &info[count].info4, snum);
4311                         break;
4312                 case 5:
4313                         result = construct_printer_info5(info, info2,
4314                                                          servername,
4315                                                          &info[count].info5, snum);
4316                         break;
4317
4318                 default:
4319                         result = WERR_UNKNOWN_LEVEL;
4320                         goto out;
4321                 }
4322
4323                 if (!W_ERROR_IS_OK(result)) {
4324                         goto out;
4325                 }
4326
4327                 count++;
4328         }
4329
4330         *count_p = count;
4331         *info_p = info;
4332
4333  out:
4334         if (!W_ERROR_IS_OK(result)) {
4335                 TALLOC_FREE(info);
4336                 return result;
4337         }
4338
4339         *info_p = info;
4340
4341         return WERR_OK;
4342 }
4343
4344 /********************************************************************
4345  * handle enumeration of printers at level 0
4346  ********************************************************************/
4347
4348 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4349                                   const struct auth_serversupplied_info *session_info,
4350                                   struct messaging_context *msg_ctx,
4351                                   uint32_t flags,
4352                                   const char *servername,
4353                                   union spoolss_PrinterInfo **info,
4354                                   uint32_t *count)
4355 {
4356         DEBUG(4,("enum_all_printers_info_0\n"));
4357
4358         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4359                                             servername, 0, flags, info, count);
4360 }
4361
4362
4363 /********************************************************************
4364 ********************************************************************/
4365
4366 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4367                                        const struct auth_serversupplied_info *session_info,
4368                                        struct messaging_context *msg_ctx,
4369                                        const char *servername,
4370                                        uint32_t flags,
4371                                        union spoolss_PrinterInfo **info,
4372                                        uint32_t *count)
4373 {
4374         DEBUG(4,("enum_all_printers_info_1\n"));
4375
4376         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4377                                             servername, 1, flags, info, count);
4378 }
4379
4380 /********************************************************************
4381  enum_all_printers_info_1_local.
4382 *********************************************************************/
4383
4384 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4385                                              const struct auth_serversupplied_info *session_info,
4386                                              struct messaging_context *msg_ctx,
4387                                              const char *servername,
4388                                              union spoolss_PrinterInfo **info,
4389                                              uint32_t *count)
4390 {
4391         DEBUG(4,("enum_all_printers_info_1_local\n"));
4392
4393         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4394                                         servername, PRINTER_ENUM_ICON8, info, count);
4395 }
4396
4397 /********************************************************************
4398  enum_all_printers_info_1_name.
4399 *********************************************************************/
4400
4401 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4402                                             const struct auth_serversupplied_info *session_info,
4403                                             struct messaging_context *msg_ctx,
4404                                             const char *servername,
4405                                             union spoolss_PrinterInfo **info,
4406                                             uint32_t *count)
4407 {
4408         const char *s = servername;
4409
4410         DEBUG(4,("enum_all_printers_info_1_name\n"));
4411
4412         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4413                 s = servername + 2;
4414         }
4415
4416         if (!is_myname_or_ipaddr(s)) {
4417                 return WERR_INVALID_NAME;
4418         }
4419
4420         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4421                                         servername, PRINTER_ENUM_ICON8, info, count);
4422 }
4423
4424 /********************************************************************
4425  enum_all_printers_info_1_network.
4426 *********************************************************************/
4427
4428 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4429                                                const struct auth_serversupplied_info *session_info,
4430                                                struct messaging_context *msg_ctx,
4431                                                const char *servername,
4432                                                union spoolss_PrinterInfo **info,
4433                                                uint32_t *count)
4434 {
4435         const char *s = servername;
4436
4437         DEBUG(4,("enum_all_printers_info_1_network\n"));
4438
4439         /* If we respond to a enum_printers level 1 on our name with flags
4440            set to PRINTER_ENUM_REMOTE with a list of printers then these
4441            printers incorrectly appear in the APW browse list.
4442            Specifically the printers for the server appear at the workgroup
4443            level where all the other servers in the domain are
4444            listed. Windows responds to this call with a
4445            WERR_CAN_NOT_COMPLETE so we should do the same. */
4446
4447         if (servername[0] == '\\' && servername[1] == '\\') {
4448                  s = servername + 2;
4449         }
4450
4451         if (is_myname_or_ipaddr(s)) {
4452                  return WERR_CAN_NOT_COMPLETE;
4453         }
4454
4455         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4456                                         servername, PRINTER_ENUM_NAME, info, count);
4457 }
4458
4459 /********************************************************************
4460  * api_spoolss_enumprinters
4461  *
4462  * called from api_spoolss_enumprinters (see this to understand)
4463  ********************************************************************/
4464
4465 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4466                                        const struct auth_serversupplied_info *session_info,
4467                                        struct messaging_context *msg_ctx,
4468                                        const char *servername,
4469                                        union spoolss_PrinterInfo **info,
4470                                        uint32_t *count)
4471 {
4472         DEBUG(4,("enum_all_printers_info_2\n"));
4473
4474         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4475                                             servername, 2, 0, info, count);
4476 }
4477
4478 /********************************************************************
4479  * handle enumeration of printers at level 1
4480  ********************************************************************/
4481
4482 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4483                                   const struct auth_serversupplied_info *session_info,
4484                                   struct messaging_context *msg_ctx,
4485                                   uint32_t flags,
4486                                   const char *servername,
4487                                   union spoolss_PrinterInfo **info,
4488                                   uint32_t *count)
4489 {
4490         /* Not all the flags are equals */
4491
4492         if (flags & PRINTER_ENUM_LOCAL) {
4493                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4494                                                       msg_ctx, servername, info, count);
4495         }
4496
4497         if (flags & PRINTER_ENUM_NAME) {
4498                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4499                                                      msg_ctx, servername, info,
4500                                                      count);
4501         }
4502
4503         if (flags & PRINTER_ENUM_NETWORK) {
4504                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4505                                                         msg_ctx, servername, info,
4506                                                         count);
4507         }
4508
4509         return WERR_OK; /* NT4sp5 does that */
4510 }
4511
4512 /********************************************************************
4513  * handle enumeration of printers at level 2
4514  ********************************************************************/
4515
4516 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4517                                   const struct auth_serversupplied_info *session_info,
4518                                   struct messaging_context *msg_ctx,
4519                                   uint32_t flags,
4520                                   const char *servername,
4521                                   union spoolss_PrinterInfo **info,
4522                                   uint32_t *count)
4523 {
4524         if (flags & PRINTER_ENUM_LOCAL) {
4525
4526                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4527                                                 servername,
4528                                                 info, count);
4529         }
4530
4531         if (flags & PRINTER_ENUM_NAME) {
4532                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4533                         return WERR_INVALID_NAME;
4534                 }
4535
4536                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4537                                                 servername,
4538                                                 info, count);
4539         }
4540
4541         if (flags & PRINTER_ENUM_REMOTE) {
4542                 return WERR_UNKNOWN_LEVEL;
4543         }
4544
4545         return WERR_OK;
4546 }
4547
4548 /********************************************************************
4549  * handle enumeration of printers at level 4
4550  ********************************************************************/
4551
4552 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4553                                   const struct auth_serversupplied_info *session_info,
4554                                   struct messaging_context *msg_ctx,
4555                                   uint32_t flags,
4556                                   const char *servername,
4557                                   union spoolss_PrinterInfo **info,
4558                                   uint32_t *count)
4559 {
4560         DEBUG(4,("enum_all_printers_info_4\n"));
4561
4562         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4563                                             servername, 4, flags, info, count);
4564 }
4565
4566
4567 /********************************************************************
4568  * handle enumeration of printers at level 5
4569  ********************************************************************/
4570
4571 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4572                                   const struct auth_serversupplied_info *session_info,
4573                                   struct messaging_context *msg_ctx,
4574                                   uint32_t flags,
4575                                   const char *servername,
4576                                   union spoolss_PrinterInfo **info,
4577                                   uint32_t *count)
4578 {
4579         DEBUG(4,("enum_all_printers_info_5\n"));
4580
4581         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4582                                             servername, 5, flags, info, count);
4583 }
4584
4585 /****************************************************************
4586  _spoolss_EnumPrinters
4587 ****************************************************************/
4588
4589 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4590                              struct spoolss_EnumPrinters *r)
4591 {
4592         const struct auth_serversupplied_info *session_info = get_session_info_system();
4593         WERROR result;
4594
4595         /* that's an [in out] buffer */
4596
4597         if (!r->in.buffer && (r->in.offered != 0)) {
4598                 return WERR_INVALID_PARAM;
4599         }
4600
4601         DEBUG(4,("_spoolss_EnumPrinters\n"));
4602
4603         *r->out.needed = 0;
4604         *r->out.count = 0;
4605         *r->out.info = NULL;
4606
4607         /*
4608          * Level 1:
4609          *          flags==PRINTER_ENUM_NAME
4610          *           if name=="" then enumerates all printers
4611          *           if name!="" then enumerate the printer
4612          *          flags==PRINTER_ENUM_REMOTE
4613          *          name is NULL, enumerate printers
4614          * Level 2: name!="" enumerates printers, name can't be NULL
4615          * Level 3: doesn't exist
4616          * Level 4: does a local registry lookup
4617          * Level 5: same as Level 2
4618          */
4619
4620         if (r->in.server && r->in.server[0] == '\0') {
4621                 r->in.server = NULL;
4622         }
4623
4624         switch (r->in.level) {
4625         case 0:
4626                 result = enumprinters_level0(p->mem_ctx, session_info,
4627                                              p->msg_ctx, r->in.flags,
4628                                              r->in.server,
4629                                              r->out.info, r->out.count);
4630                 break;
4631         case 1:
4632                 result = enumprinters_level1(p->mem_ctx, session_info,
4633                                              p->msg_ctx, r->in.flags,
4634                                              r->in.server,
4635                                              r->out.info, r->out.count);
4636                 break;
4637         case 2:
4638                 result = enumprinters_level2(p->mem_ctx, session_info,
4639                                              p->msg_ctx, r->in.flags,
4640                                              r->in.server,
4641                                              r->out.info, r->out.count);
4642                 break;
4643         case 4:
4644                 result = enumprinters_level4(p->mem_ctx, session_info,
4645                                              p->msg_ctx, r->in.flags,
4646                                              r->in.server,
4647                                              r->out.info, r->out.count);
4648                 break;
4649         case 5:
4650                 result = enumprinters_level5(p->mem_ctx, session_info,
4651                                              p->msg_ctx, r->in.flags,
4652                                              r->in.server,
4653                                              r->out.info, r->out.count);
4654                 break;
4655         default:
4656                 return WERR_UNKNOWN_LEVEL;
4657         }
4658
4659         if (!W_ERROR_IS_OK(result)) {
4660                 return result;
4661         }
4662
4663         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4664                                                      spoolss_EnumPrinters,
4665                                                      *r->out.info, r->in.level,
4666                                                      *r->out.count);
4667         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4668         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4669
4670         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4671 }
4672
4673 /****************************************************************
4674  _spoolss_GetPrinter
4675 ****************************************************************/
4676
4677 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4678                            struct spoolss_GetPrinter *r)
4679 {
4680         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4681         struct spoolss_PrinterInfo2 *info2 = NULL;
4682         WERROR result = WERR_OK;
4683         int snum;
4684
4685         /* that's an [in out] buffer */
4686
4687         if (!r->in.buffer && (r->in.offered != 0)) {
4688                 return WERR_INVALID_PARAM;
4689         }
4690
4691         *r->out.needed = 0;
4692
4693         if (Printer == NULL) {
4694                 return WERR_BADFID;
4695         }
4696
4697         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4698                 return WERR_BADFID;
4699         }
4700
4701         result = winreg_get_printer(p->mem_ctx,
4702                                     get_session_info_system(),
4703                                     p->msg_ctx,
4704                                     lp_const_servicename(snum),
4705                                     &info2);
4706         if (!W_ERROR_IS_OK(result)) {
4707                 goto out;
4708         }
4709
4710         switch (r->in.level) {
4711         case 0:
4712                 result = construct_printer_info0(p->mem_ctx,
4713                                                  get_session_info_system(),
4714                                                  p->msg_ctx,
4715                                                  info2,
4716                                                  Printer->servername,
4717                                                  &r->out.info->info0,
4718                                                  snum);
4719                 break;
4720         case 1:
4721                 result = construct_printer_info1(p->mem_ctx, info2,
4722                                                  PRINTER_ENUM_ICON8,
4723                                                  Printer->servername,
4724                                                  &r->out.info->info1, snum);
4725                 break;
4726         case 2:
4727                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4728                                                  Printer->servername,
4729                                                  &r->out.info->info2, snum);
4730                 break;
4731         case 3:
4732                 result = construct_printer_info3(p->mem_ctx, info2,
4733                                                  Printer->servername,
4734                                                  &r->out.info->info3, snum);
4735                 break;
4736         case 4:
4737                 result = construct_printer_info4(p->mem_ctx, info2,
4738                                                  Printer->servername,
4739                                                  &r->out.info->info4, snum);
4740                 break;
4741         case 5:
4742                 result = construct_printer_info5(p->mem_ctx, info2,
4743                                                  Printer->servername,
4744                                                  &r->out.info->info5, snum);
4745                 break;
4746         case 6:
4747                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4748                                                  Printer->servername,
4749                                                  &r->out.info->info6, snum);
4750                 break;
4751         case 7:
4752                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4753                                                  Printer->servername,
4754                                                  &r->out.info->info7, snum);
4755                 break;
4756         case 8:
4757                 result = construct_printer_info8(p->mem_ctx, info2,
4758                                                  Printer->servername,
4759                                                  &r->out.info->info8, snum);
4760                 break;
4761         default:
4762                 result = WERR_UNKNOWN_LEVEL;
4763                 break;
4764         }
4765
4766  out:
4767         if (!W_ERROR_IS_OK(result)) {
4768                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4769                           r->in.level, win_errstr(result)));
4770                 TALLOC_FREE(r->out.info);
4771                 return result;
4772         }
4773
4774         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4775                                                r->out.info, r->in.level);
4776         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4777
4778         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4779 }
4780
4781 /********************************************************************
4782  ********************************************************************/
4783
4784 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4785         do { \
4786                 if (in && strlen(in)) { \
4787                         out = talloc_strdup(mem_ctx, in); \
4788                 } else { \
4789                         out = talloc_strdup(mem_ctx, ""); \
4790                 } \
4791                 W_ERROR_HAVE_NO_MEMORY(out); \
4792         } while (0);
4793
4794 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4795         do { \
4796                 if (in && strlen(in)) { \
4797                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4798                 } else { \
4799                         out = talloc_strdup(mem_ctx, ""); \
4800                 } \
4801                 W_ERROR_HAVE_NO_MEMORY(out); \
4802         } while (0);
4803
4804 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4805                                                   const char **string_array,
4806                                                   const char ***presult,
4807                                                   const char *cservername,
4808                                                   const char *arch,
4809                                                   int version)
4810 {
4811         int i, num_strings = 0;
4812         const char **array = NULL;
4813
4814         if (string_array == NULL) {
4815                 return WERR_INVALID_PARAMETER;
4816         }
4817
4818         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4819                 const char *str = NULL;
4820
4821                 if (cservername == NULL || arch == NULL) {
4822                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4823                 } else {
4824                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4825                 }
4826
4827                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4828                         TALLOC_FREE(array);
4829                         return WERR_NOMEM;
4830                 }
4831         }
4832
4833         if (i > 0) {
4834                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4835                              &array, &num_strings);
4836         }
4837
4838         if (presult) {
4839                 *presult = array;
4840         }
4841
4842         return WERR_OK;
4843 }
4844
4845 /********************************************************************
4846  * fill a spoolss_DriverInfo1 struct
4847  ********************************************************************/
4848
4849 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4850                                         struct spoolss_DriverInfo1 *r,
4851                                         const struct spoolss_DriverInfo8 *driver,
4852                                         const char *servername)
4853 {
4854         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4855         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4856
4857         return WERR_OK;
4858 }
4859
4860 /********************************************************************
4861  * fill a spoolss_DriverInfo2 struct
4862  ********************************************************************/
4863
4864 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4865                                         struct spoolss_DriverInfo2 *r,
4866                                         const struct spoolss_DriverInfo8 *driver,
4867                                         const char *servername)
4868
4869 {
4870         const char *cservername = canon_servername(servername);
4871
4872         r->version              = driver->version;
4873
4874         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4875         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4876         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4877         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4878
4879         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4880                                driver->architecture,
4881                                driver->version,
4882                                driver->driver_path,
4883                                r->driver_path);
4884
4885         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4886                                driver->architecture,
4887                                driver->version,
4888                                driver->data_file,
4889                                r->data_file);
4890
4891         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4892                                driver->architecture,
4893                                driver->version,
4894                                driver->config_file,
4895                                r->config_file);
4896
4897         return WERR_OK;
4898 }
4899
4900 /********************************************************************
4901  * fill a spoolss_DriverInfo3 struct
4902  ********************************************************************/
4903
4904 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4905                                         struct spoolss_DriverInfo3 *r,
4906                                         const struct spoolss_DriverInfo8 *driver,
4907                                         const char *servername)
4908 {
4909         const char *cservername = canon_servername(servername);
4910
4911         r->version              = driver->version;
4912
4913         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4914         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4915         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4916         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4917
4918         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4919                                driver->architecture,
4920                                driver->version,
4921                                driver->driver_path,
4922                                r->driver_path);
4923
4924         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4925                                driver->architecture,
4926                                driver->version,
4927                                driver->data_file,
4928                                r->data_file);
4929
4930         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4931                                driver->architecture,
4932                                driver->version,
4933                                driver->config_file,
4934                                r->config_file);
4935
4936         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4937                                driver->architecture,
4938                                driver->version,
4939                                driver->help_file,
4940                                r->help_file);
4941
4942         FILL_DRIVER_STRING(mem_ctx,
4943                            driver->monitor_name,
4944                            r->monitor_name);
4945
4946         FILL_DRIVER_STRING(mem_ctx,
4947                            driver->default_datatype,
4948                            r->default_datatype);
4949
4950         return string_array_from_driver_info(mem_ctx,
4951                                              driver->dependent_files,
4952                                              &r->dependent_files,
4953                                              cservername,
4954                                              driver->architecture,
4955                                              driver->version);
4956 }
4957
4958 /********************************************************************
4959  * fill a spoolss_DriverInfo4 struct
4960  ********************************************************************/
4961
4962 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4963                                         struct spoolss_DriverInfo4 *r,
4964                                         const struct spoolss_DriverInfo8 *driver,
4965                                         const char *servername)
4966 {
4967         const char *cservername = canon_servername(servername);
4968         WERROR result;
4969
4970         r->version              = driver->version;
4971
4972         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4973         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4974         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4975         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4976
4977         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4978                                driver->architecture,
4979                                driver->version,
4980                                driver->driver_path,
4981                                r->driver_path);
4982
4983         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4984                                driver->architecture,
4985                                driver->version,
4986                                driver->data_file,
4987                                r->data_file);
4988
4989         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4990                                driver->architecture,
4991                                driver->version,
4992                                driver->config_file,
4993                                r->config_file);
4994
4995         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4996                                driver->architecture,
4997                                driver->version,
4998                                driver->help_file,
4999                                r->help_file);
5000
5001         result = string_array_from_driver_info(mem_ctx,
5002                                                driver->dependent_files,
5003                                                &r->dependent_files,
5004                                                cservername,
5005                                                driver->architecture,
5006                                                driver->version);
5007         if (!W_ERROR_IS_OK(result)) {
5008                 return result;
5009         }
5010
5011         FILL_DRIVER_STRING(mem_ctx,
5012                            driver->monitor_name,
5013                            r->monitor_name);
5014
5015         FILL_DRIVER_STRING(mem_ctx,
5016                            driver->default_datatype,
5017                            r->default_datatype);
5018
5019
5020         result = string_array_from_driver_info(mem_ctx,
5021                                                driver->previous_names,
5022                                                &r->previous_names,
5023                                                NULL, NULL, 0);
5024
5025         return result;
5026 }
5027
5028 /********************************************************************
5029  * fill a spoolss_DriverInfo5 struct
5030  ********************************************************************/
5031
5032 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5033                                         struct spoolss_DriverInfo5 *r,
5034                                         const struct spoolss_DriverInfo8 *driver,
5035                                         const char *servername)
5036 {
5037         const char *cservername = canon_servername(servername);
5038
5039         r->version              = driver->version;
5040
5041         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5042         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5043         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5044         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5045
5046         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5047                                driver->architecture,
5048                                driver->version,
5049                                driver->driver_path,
5050                                r->driver_path);
5051
5052         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5053                                driver->architecture,
5054                                driver->version,
5055                                driver->data_file,
5056                                r->data_file);
5057
5058         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5059                                driver->architecture,
5060                                driver->version,
5061                                driver->config_file,
5062                                r->config_file);
5063
5064         r->driver_attributes    = 0;
5065         r->config_version       = 0;
5066         r->driver_version       = 0;
5067
5068         return WERR_OK;
5069 }
5070 /********************************************************************
5071  * fill a spoolss_DriverInfo6 struct
5072  ********************************************************************/
5073
5074 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5075                                         struct spoolss_DriverInfo6 *r,
5076                                         const struct spoolss_DriverInfo8 *driver,
5077                                         const char *servername)
5078 {
5079         const char *cservername = canon_servername(servername);
5080         WERROR result;
5081
5082         r->version              = driver->version;
5083
5084         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5085         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5086         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5087         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5088
5089         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5090                                driver->architecture,
5091                                driver->version,
5092                                driver->driver_path,
5093                                r->driver_path);
5094
5095         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5096                                driver->architecture,
5097                                driver->version,
5098                                driver->data_file,
5099                                r->data_file);
5100
5101         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5102                                driver->architecture,
5103                                driver->version,
5104                                driver->config_file,
5105                                r->config_file);
5106
5107         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5108                                driver->architecture,
5109                                driver->version,
5110                                driver->help_file,
5111                                r->help_file);
5112
5113         FILL_DRIVER_STRING(mem_ctx,
5114                            driver->monitor_name,
5115                            r->monitor_name);
5116
5117         FILL_DRIVER_STRING(mem_ctx,
5118                            driver->default_datatype,
5119                            r->default_datatype);
5120
5121         result = string_array_from_driver_info(mem_ctx,
5122                                                driver->dependent_files,
5123                                                &r->dependent_files,
5124                                                cservername,
5125                                                driver->architecture,
5126                                                driver->version);
5127         if (!W_ERROR_IS_OK(result)) {
5128                 return result;
5129         }
5130
5131         result = string_array_from_driver_info(mem_ctx,
5132                                                driver->previous_names,
5133                                                &r->previous_names,
5134                                                NULL, NULL, 0);
5135         if (!W_ERROR_IS_OK(result)) {
5136                 return result;
5137         }
5138
5139         r->driver_date          = driver->driver_date;
5140         r->driver_version       = driver->driver_version;
5141
5142         FILL_DRIVER_STRING(mem_ctx,
5143                            driver->manufacturer_name,
5144                            r->manufacturer_name);
5145         FILL_DRIVER_STRING(mem_ctx,
5146                            driver->manufacturer_url,
5147                            r->manufacturer_url);
5148         FILL_DRIVER_STRING(mem_ctx,
5149                            driver->hardware_id,
5150                            r->hardware_id);
5151         FILL_DRIVER_STRING(mem_ctx,
5152                            driver->provider,
5153                            r->provider);
5154
5155         return WERR_OK;
5156 }
5157
5158 /********************************************************************
5159  * fill a spoolss_DriverInfo8 struct
5160  ********************************************************************/
5161
5162 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5163                                         struct spoolss_DriverInfo8 *r,
5164                                         const struct spoolss_DriverInfo8 *driver,
5165                                         const char *servername)
5166 {
5167         const char *cservername = canon_servername(servername);
5168         WERROR result;
5169
5170         r->version              = driver->version;
5171
5172         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5173         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5174         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5175         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5176
5177         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5178                                driver->architecture,
5179                                driver->version,
5180                                driver->driver_path,
5181                                r->driver_path);
5182
5183         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5184                                driver->architecture,
5185                                driver->version,
5186                                driver->data_file,
5187                                r->data_file);
5188
5189         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5190                                driver->architecture,
5191                                driver->version,
5192                                driver->config_file,
5193                                r->config_file);
5194
5195         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5196                                driver->architecture,
5197                                driver->version,
5198                                driver->help_file,
5199                                r->help_file);
5200
5201         FILL_DRIVER_STRING(mem_ctx,
5202                            driver->monitor_name,
5203                            r->monitor_name);
5204
5205         FILL_DRIVER_STRING(mem_ctx,
5206                            driver->default_datatype,
5207                            r->default_datatype);
5208
5209         result = string_array_from_driver_info(mem_ctx,
5210                                                driver->dependent_files,
5211                                                &r->dependent_files,
5212                                                cservername,
5213                                                driver->architecture,
5214                                                driver->version);
5215         if (!W_ERROR_IS_OK(result)) {
5216                 return result;
5217         }
5218
5219         result = string_array_from_driver_info(mem_ctx,
5220                                                driver->previous_names,
5221                                                &r->previous_names,
5222                                                NULL, NULL, 0);
5223         if (!W_ERROR_IS_OK(result)) {
5224                 return result;
5225         }
5226
5227         r->driver_date          = driver->driver_date;
5228         r->driver_version       = driver->driver_version;
5229
5230         FILL_DRIVER_STRING(mem_ctx,
5231                            driver->manufacturer_name,
5232                            r->manufacturer_name);
5233         FILL_DRIVER_STRING(mem_ctx,
5234                            driver->manufacturer_url,
5235                            r->manufacturer_url);
5236         FILL_DRIVER_STRING(mem_ctx,
5237                            driver->hardware_id,
5238                            r->hardware_id);
5239         FILL_DRIVER_STRING(mem_ctx,
5240                            driver->provider,
5241                            r->provider);
5242
5243         FILL_DRIVER_STRING(mem_ctx,
5244                            driver->print_processor,
5245                            r->print_processor);
5246         FILL_DRIVER_STRING(mem_ctx,
5247                            driver->vendor_setup,
5248                            r->vendor_setup);
5249
5250         result = string_array_from_driver_info(mem_ctx,
5251                                                driver->color_profiles,
5252                                                &r->color_profiles,
5253                                                NULL, NULL, 0);
5254         if (!W_ERROR_IS_OK(result)) {
5255                 return result;
5256         }
5257
5258         FILL_DRIVER_STRING(mem_ctx,
5259                            driver->inf_path,
5260                            r->inf_path);
5261
5262         r->printer_driver_attributes    = driver->printer_driver_attributes;
5263
5264         result = string_array_from_driver_info(mem_ctx,
5265                                                driver->core_driver_dependencies,
5266                                                &r->core_driver_dependencies,
5267                                                NULL, NULL, 0);
5268         if (!W_ERROR_IS_OK(result)) {
5269                 return result;
5270         }
5271
5272         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5273         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5274
5275         return WERR_OK;
5276 }
5277
5278 #if 0 /* disabled until marshalling issues are resolved - gd */
5279 /********************************************************************
5280  ********************************************************************/
5281
5282 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5283                                           struct spoolss_DriverFileInfo *r,
5284                                           const char *cservername,
5285                                           const char *file_name,
5286                                           enum spoolss_DriverFileType file_type,
5287                                           uint32_t file_version)
5288 {
5289         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5290                                           cservername, file_name);
5291         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5292         r->file_type    = file_type;
5293         r->file_version = file_version;
5294
5295         return WERR_OK;
5296 }
5297
5298 /********************************************************************
5299  ********************************************************************/
5300
5301 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5302                                                  const struct spoolss_DriverInfo8 *driver,
5303                                                  const char *cservername,
5304                                                  struct spoolss_DriverFileInfo **info_p,
5305                                                  uint32_t *count_p)
5306 {
5307         struct spoolss_DriverFileInfo *info = NULL;
5308         uint32_t count = 0;
5309         WERROR result;
5310         uint32_t i;
5311
5312         *info_p = NULL;
5313         *count_p = 0;
5314
5315         if (strlen(driver->driver_path)) {
5316                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5317                                             struct spoolss_DriverFileInfo,
5318                                             count + 1);
5319                 W_ERROR_HAVE_NO_MEMORY(info);
5320                 result = fill_spoolss_DriverFileInfo(info,
5321                                                      &info[count],
5322                                                      cservername,
5323                                                      driver->driver_path,
5324                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5325                                                      0);
5326                 W_ERROR_NOT_OK_RETURN(result);
5327                 count++;
5328         }
5329
5330         if (strlen(driver->config_file)) {
5331                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5332                                             struct spoolss_DriverFileInfo,
5333                                             count + 1);
5334                 W_ERROR_HAVE_NO_MEMORY(info);
5335                 result = fill_spoolss_DriverFileInfo(info,
5336                                                      &info[count],
5337                                                      cservername,
5338                                                      driver->config_file,
5339                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5340                                                      0);
5341                 W_ERROR_NOT_OK_RETURN(result);
5342                 count++;
5343         }
5344
5345         if (strlen(driver->data_file)) {
5346                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5347                                             struct spoolss_DriverFileInfo,
5348                                             count + 1);
5349                 W_ERROR_HAVE_NO_MEMORY(info);
5350                 result = fill_spoolss_DriverFileInfo(info,
5351                                                      &info[count],
5352                                                      cservername,
5353                                                      driver->data_file,
5354                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5355                                                      0);
5356                 W_ERROR_NOT_OK_RETURN(result);
5357                 count++;
5358         }
5359
5360         if (strlen(driver->help_file)) {
5361                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5362                                             struct spoolss_DriverFileInfo,
5363                                             count + 1);
5364                 W_ERROR_HAVE_NO_MEMORY(info);
5365                 result = fill_spoolss_DriverFileInfo(info,
5366                                                      &info[count],
5367                                                      cservername,
5368                                                      driver->help_file,
5369                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5370                                                      0);
5371                 W_ERROR_NOT_OK_RETURN(result);
5372                 count++;
5373         }
5374
5375         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5376                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5377                                             struct spoolss_DriverFileInfo,
5378                                             count + 1);
5379                 W_ERROR_HAVE_NO_MEMORY(info);
5380                 result = fill_spoolss_DriverFileInfo(info,
5381                                                      &info[count],
5382                                                      cservername,
5383                                                      driver->dependent_files[i],
5384                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5385                                                      0);
5386                 W_ERROR_NOT_OK_RETURN(result);
5387                 count++;
5388         }
5389
5390         *info_p = info;
5391         *count_p = count;
5392
5393         return WERR_OK;
5394 }
5395
5396 /********************************************************************
5397  * fill a spoolss_DriverInfo101 struct
5398  ********************************************************************/
5399
5400 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5401                                           struct spoolss_DriverInfo101 *r,
5402                                           const struct spoolss_DriverInfo8 *driver,
5403                                           const char *servername)
5404 {
5405         const char *cservername = canon_servername(servername);
5406         WERROR result;
5407
5408         r->version              = driver->version;
5409
5410         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5411         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5412         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5413         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5414
5415         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5416                                                     cservername,
5417                                                     &r->file_info,
5418                                                     &r->file_count);
5419         if (!W_ERROR_IS_OK(result)) {
5420                 return result;
5421         }
5422
5423         FILL_DRIVER_STRING(mem_ctx,
5424                            driver->monitor_name,
5425                            r->monitor_name);
5426
5427         FILL_DRIVER_STRING(mem_ctx,
5428                            driver->default_datatype,
5429                            r->default_datatype);
5430
5431         result = string_array_from_driver_info(mem_ctx,
5432                                                driver->previous_names,
5433                                                &r->previous_names,
5434                                                NULL, NULL, 0);
5435         if (!W_ERROR_IS_OK(result)) {
5436                 return result;
5437         }
5438
5439         r->driver_date          = driver->driver_date;
5440         r->driver_version       = driver->driver_version;
5441
5442         FILL_DRIVER_STRING(mem_ctx,
5443                            driver->manufacturer_name,
5444                            r->manufacturer_name);
5445         FILL_DRIVER_STRING(mem_ctx,
5446                            driver->manufacturer_url,
5447                            r->manufacturer_url);
5448         FILL_DRIVER_STRING(mem_ctx,
5449                            driver->hardware_id,
5450                            r->hardware_id);
5451         FILL_DRIVER_STRING(mem_ctx,
5452                            driver->provider,
5453                            r->provider);
5454
5455         return WERR_OK;
5456 }
5457 #endif
5458 /********************************************************************
5459  ********************************************************************/
5460
5461 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5462                                                   const struct auth_serversupplied_info *session_info,
5463                                                   struct messaging_context *msg_ctx,
5464                                                   uint32_t level,
5465                                                   union spoolss_DriverInfo *r,
5466                                                   int snum,
5467                                                   const char *servername,
5468                                                   const char *architecture,
5469                                                   uint32_t version)
5470 {
5471         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5472         struct spoolss_DriverInfo8 *driver;
5473         WERROR result;
5474
5475         if (level == 101) {
5476                 return WERR_UNKNOWN_LEVEL;
5477         }
5478
5479         result = winreg_get_printer(mem_ctx,
5480                                     session_info,
5481                                     msg_ctx,
5482                                     lp_const_servicename(snum),
5483                                     &pinfo2);
5484
5485         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5486                 win_errstr(result)));
5487
5488         if (!W_ERROR_IS_OK(result)) {
5489                 return WERR_INVALID_PRINTER_NAME;
5490         }
5491
5492         result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5493                                    architecture,
5494                                    pinfo2->drivername, version, &driver);
5495
5496         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5497                 win_errstr(result)));
5498
5499         if (!W_ERROR_IS_OK(result)) {
5500                 /*
5501                  * Is this a W2k client ?
5502                  */
5503
5504                 if (version < 3) {
5505                         talloc_free(pinfo2);
5506                         return WERR_UNKNOWN_PRINTER_DRIVER;
5507                 }
5508
5509                 /* Yes - try again with a WinNT driver. */
5510                 version = 2;
5511                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5512                                            architecture,
5513                                            pinfo2->drivername,
5514                                            version, &driver);
5515                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5516                         win_errstr(result)));
5517                 if (!W_ERROR_IS_OK(result)) {
5518                         talloc_free(pinfo2);
5519                         return WERR_UNKNOWN_PRINTER_DRIVER;
5520                 }
5521         }
5522
5523         switch (level) {
5524         case 1:
5525                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5526                 break;
5527         case 2:
5528                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5529                 break;
5530         case 3:
5531                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5532                 break;
5533         case 4:
5534                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5535                 break;
5536         case 5:
5537                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5538                 break;
5539         case 6:
5540                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5541                 break;
5542         case 8:
5543                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5544                 break;
5545 #if 0 /* disabled until marshalling issues are resolved - gd */
5546         case 101:
5547                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5548                 break;
5549 #endif
5550         default:
5551                 result = WERR_UNKNOWN_LEVEL;
5552                 break;
5553         }
5554
5555         talloc_free(pinfo2);
5556         talloc_free(driver);
5557
5558         return result;
5559 }
5560
5561 /****************************************************************
5562  _spoolss_GetPrinterDriver2
5563 ****************************************************************/
5564
5565 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5566                                   struct spoolss_GetPrinterDriver2 *r)
5567 {
5568         struct printer_handle *printer;
5569         WERROR result;
5570
5571         int snum;
5572
5573         /* that's an [in out] buffer */
5574
5575         if (!r->in.buffer && (r->in.offered != 0)) {
5576                 return WERR_INVALID_PARAM;
5577         }
5578
5579         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5580
5581         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5582                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5583                 return WERR_INVALID_PRINTER_NAME;
5584         }
5585
5586         *r->out.needed = 0;
5587         *r->out.server_major_version = 0;
5588         *r->out.server_minor_version = 0;
5589
5590         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5591                 return WERR_BADFID;
5592         }
5593
5594         result = construct_printer_driver_info_level(p->mem_ctx,
5595                                                      get_session_info_system(),
5596                                                      p->msg_ctx,
5597                                                      r->in.level, r->out.info,
5598                                                      snum, printer->servername,
5599                                                      r->in.architecture,
5600                                                      r->in.client_major_version);
5601         if (!W_ERROR_IS_OK(result)) {
5602                 TALLOC_FREE(r->out.info);
5603                 return result;
5604         }
5605
5606         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5607                                                r->out.info, r->in.level);
5608         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5609
5610         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5611 }
5612
5613
5614 /****************************************************************
5615  _spoolss_StartPagePrinter
5616 ****************************************************************/
5617
5618 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5619                                  struct spoolss_StartPagePrinter *r)
5620 {
5621         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5622
5623         if (!Printer) {
5624                 DEBUG(3,("_spoolss_StartPagePrinter: "
5625                         "Error in startpageprinter printer handle\n"));
5626                 return WERR_BADFID;
5627         }
5628
5629         Printer->page_started = true;
5630         return WERR_OK;
5631 }
5632
5633 /****************************************************************
5634  _spoolss_EndPagePrinter
5635 ****************************************************************/
5636
5637 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5638                                struct spoolss_EndPagePrinter *r)
5639 {
5640         int snum;
5641
5642         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5643
5644         if (!Printer) {
5645                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5646                         OUR_HANDLE(r->in.handle)));
5647                 return WERR_BADFID;
5648         }
5649
5650         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5651                 return WERR_BADFID;
5652
5653         Printer->page_started = false;
5654         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5655
5656         return WERR_OK;
5657 }
5658
5659 /****************************************************************
5660  _spoolss_StartDocPrinter
5661 ****************************************************************/
5662
5663 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5664                                 struct spoolss_StartDocPrinter *r)
5665 {
5666         struct spoolss_DocumentInfo1 *info_1;
5667         int snum;
5668         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5669         WERROR werr;
5670
5671         if (!Printer) {
5672                 DEBUG(2,("_spoolss_StartDocPrinter: "
5673                         "Invalid handle (%s:%u:%u)\n",
5674                         OUR_HANDLE(r->in.handle)));
5675                 return WERR_BADFID;
5676         }
5677
5678         if (Printer->jobid) {
5679                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5680                           "StartDocPrinter called twice! "
5681                           "(existing jobid = %d)\n", Printer->jobid));
5682                 return WERR_INVALID_HANDLE;
5683         }
5684
5685         if (r->in.level != 1) {
5686                 return WERR_UNKNOWN_LEVEL;
5687         }
5688
5689         info_1 = r->in.info.info1;
5690
5691         /*
5692          * a nice thing with NT is it doesn't listen to what you tell it.
5693          * when asked to send _only_ RAW datas, it tries to send datas
5694          * in EMF format.
5695          *
5696          * So I add checks like in NT Server ...
5697          */
5698
5699         if (info_1->datatype) {
5700                 if (strcmp(info_1->datatype, "RAW") != 0) {
5701                         *r->out.job_id = 0;
5702                         return WERR_INVALID_DATATYPE;
5703                 }
5704         }
5705
5706         /* get the share number of the printer */
5707         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5708                 return WERR_BADFID;
5709         }
5710
5711         werr = print_job_start(p->session_info,
5712                                p->msg_ctx,
5713                                p->client_id->name,
5714                                snum,
5715                                info_1->document_name,
5716                                info_1->output_file,
5717                                Printer->devmode,
5718                                &Printer->jobid);
5719
5720         /* An error occured in print_job_start() so return an appropriate
5721            NT error code. */
5722
5723         if (!W_ERROR_IS_OK(werr)) {
5724                 return werr;
5725         }
5726
5727         Printer->document_started = true;
5728         *r->out.job_id = Printer->jobid;
5729
5730         return WERR_OK;
5731 }
5732
5733 /****************************************************************
5734  _spoolss_EndDocPrinter
5735 ****************************************************************/
5736
5737 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5738                               struct spoolss_EndDocPrinter *r)
5739 {
5740         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5741         NTSTATUS status;
5742         int snum;
5743
5744         if (!Printer) {
5745                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5746                         OUR_HANDLE(r->in.handle)));
5747                 return WERR_BADFID;
5748         }
5749
5750         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5751                 return WERR_BADFID;
5752         }
5753
5754         Printer->document_started = false;
5755         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5756         if (!NT_STATUS_IS_OK(status)) {
5757                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5758                           "print_job_end failed [%s]\n",
5759                           nt_errstr(status)));
5760         }
5761
5762         Printer->jobid = 0;
5763         return ntstatus_to_werror(status);
5764 }
5765
5766 /****************************************************************
5767  _spoolss_WritePrinter
5768 ****************************************************************/
5769
5770 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5771                              struct spoolss_WritePrinter *r)
5772 {
5773         ssize_t buffer_written;
5774         int snum;
5775         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5776
5777         if (!Printer) {
5778                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5779                         OUR_HANDLE(r->in.handle)));
5780                 *r->out.num_written = r->in._data_size;
5781                 return WERR_BADFID;
5782         }
5783
5784         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5785                 return WERR_BADFID;
5786
5787         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5788         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5789                                                    snum, Printer->jobid,
5790                                                    (const char *)r->in.data.data,
5791                                                    (size_t)r->in._data_size);
5792         if (buffer_written == (ssize_t)-1) {
5793                 *r->out.num_written = 0;
5794                 if (errno == ENOSPC)
5795                         return WERR_NO_SPOOL_SPACE;
5796                 else
5797                         return WERR_ACCESS_DENIED;
5798         }
5799
5800         *r->out.num_written = r->in._data_size;
5801
5802         return WERR_OK;
5803 }
5804
5805 /********************************************************************
5806  * api_spoolss_getprinter
5807  * called from the spoolss dispatcher
5808  *
5809  ********************************************************************/
5810
5811 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5812                               struct pipes_struct *p)
5813 {
5814         const struct auth_serversupplied_info *session_info = p->session_info;
5815         int snum;
5816         WERROR errcode = WERR_BADFUNC;
5817         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5818
5819         if (!Printer) {
5820                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5821                         OUR_HANDLE(handle)));
5822                 return WERR_BADFID;
5823         }
5824
5825         if (!get_printer_snum(p, handle, &snum, NULL))
5826                 return WERR_BADFID;
5827
5828         switch (command) {
5829         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5830                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5831                 break;
5832         case SPOOLSS_PRINTER_CONTROL_RESUME:
5833         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5834                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5835                 break;
5836         case SPOOLSS_PRINTER_CONTROL_PURGE:
5837                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5838                 break;
5839         default:
5840                 return WERR_UNKNOWN_LEVEL;
5841         }
5842
5843         return errcode;
5844 }
5845
5846
5847 /****************************************************************
5848  _spoolss_AbortPrinter
5849  * From MSDN: "Deletes printer's spool file if printer is configured
5850  * for spooling"
5851 ****************************************************************/
5852
5853 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5854                              struct spoolss_AbortPrinter *r)
5855 {
5856         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5857         int             snum;
5858         WERROR          errcode = WERR_OK;
5859
5860         if (!Printer) {
5861                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5862                         OUR_HANDLE(r->in.handle)));
5863                 return WERR_BADFID;
5864         }
5865
5866         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5867                 return WERR_BADFID;
5868
5869         if (!Printer->document_started) {
5870                 return WERR_SPL_NO_STARTDOC;
5871         }
5872
5873         errcode = print_job_delete(p->session_info,
5874                                    p->msg_ctx,
5875                                    snum,
5876                                    Printer->jobid);
5877
5878         return errcode;
5879 }
5880
5881 /********************************************************************
5882  * called by spoolss_api_setprinter
5883  * when updating a printer description
5884  ********************************************************************/
5885
5886 static WERROR update_printer_sec(struct policy_handle *handle,
5887                                  struct pipes_struct *p,
5888                                  struct sec_desc_buf *secdesc_ctr)
5889 {
5890         struct spoolss_security_descriptor *new_secdesc = NULL;
5891         struct spoolss_security_descriptor *old_secdesc = NULL;
5892         const char *printer;
5893         WERROR result;
5894         int snum;
5895
5896         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5897
5898         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5899                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5900                          OUR_HANDLE(handle)));
5901
5902                 result = WERR_BADFID;
5903                 goto done;
5904         }
5905
5906         if (secdesc_ctr == NULL) {
5907                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5908                 result = WERR_INVALID_PARAM;
5909                 goto done;
5910         }
5911         printer = lp_const_servicename(snum);
5912
5913         /* Check the user has permissions to change the security
5914            descriptor.  By experimentation with two NT machines, the user
5915            requires Full Access to the printer to change security
5916            information. */
5917
5918         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5919                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5920                 result = WERR_ACCESS_DENIED;
5921                 goto done;
5922         }
5923
5924         /* NT seems to like setting the security descriptor even though
5925            nothing may have actually changed. */
5926         result = winreg_get_printer_secdesc(p->mem_ctx,
5927                                             get_session_info_system(),
5928                                             p->msg_ctx,
5929                                             printer,
5930                                             &old_secdesc);
5931         if (!W_ERROR_IS_OK(result)) {
5932                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5933                 result = WERR_BADFID;
5934                 goto done;
5935         }
5936
5937         if (DEBUGLEVEL >= 10) {
5938                 struct security_acl *the_acl;
5939                 int i;
5940
5941                 the_acl = old_secdesc->dacl;
5942                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5943                            printer, the_acl->num_aces));
5944
5945                 for (i = 0; i < the_acl->num_aces; i++) {
5946                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5947                                            &the_acl->aces[i].trustee),
5948                                   the_acl->aces[i].access_mask));
5949                 }
5950
5951                 the_acl = secdesc_ctr->sd->dacl;
5952
5953                 if (the_acl) {
5954                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5955                                    printer, the_acl->num_aces));
5956
5957                         for (i = 0; i < the_acl->num_aces; i++) {
5958                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5959                                                    &the_acl->aces[i].trustee),
5960                                            the_acl->aces[i].access_mask));
5961                         }
5962                 } else {
5963                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5964                 }
5965         }
5966
5967         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5968         if (new_secdesc == NULL) {
5969                 result = WERR_NOMEM;
5970                 goto done;
5971         }
5972
5973         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5974                 result = WERR_OK;
5975                 goto done;
5976         }
5977
5978         result = winreg_set_printer_secdesc(p->mem_ctx,
5979                                             get_session_info_system(),
5980                                             p->msg_ctx,
5981                                             printer,
5982                                             new_secdesc);
5983
5984  done:
5985         return result;
5986 }
5987
5988 /********************************************************************
5989  Canonicalize printer info from a client
5990  ********************************************************************/
5991
5992 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5993                              struct spoolss_SetPrinterInfo2 *info2,
5994                              int snum)
5995 {
5996         fstring printername;
5997         const char *p;
5998
5999         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6000                 "portname=%s drivername=%s comment=%s location=%s\n",
6001                 info2->servername, info2->printername, info2->sharename,
6002                 info2->portname, info2->drivername, info2->comment,
6003                 info2->location));
6004
6005         /* we force some elements to "correct" values */
6006         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6007         if (info2->servername == NULL) {
6008                 return false;
6009         }
6010         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6011         if (info2->sharename == NULL) {
6012                 return false;
6013         }
6014
6015         /* check to see if we allow printername != sharename */
6016         if (lp_force_printername(snum)) {
6017                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6018                                         global_myname(), info2->sharename);
6019         } else {
6020                 /* make sure printername is in \\server\printername format */
6021                 fstrcpy(printername, info2->printername);
6022                 p = printername;
6023                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6024                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6025                                 p++;
6026                 }
6027
6028                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6029                                         global_myname(), p);
6030         }
6031         if (info2->printername == NULL) {
6032                 return false;
6033         }
6034
6035         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6036         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6037
6038         return true;
6039 }
6040
6041 /****************************************************************************
6042 ****************************************************************************/
6043
6044 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6045 {
6046         char *cmd = lp_addport_cmd();
6047         char *command = NULL;
6048         int ret;
6049         bool is_print_op = false;
6050
6051         if ( !*cmd ) {
6052                 return WERR_ACCESS_DENIED;
6053         }
6054
6055         command = talloc_asprintf(ctx,
6056                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6057         if (!command) {
6058                 return WERR_NOMEM;
6059         }
6060
6061         if ( token )
6062                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6063
6064         DEBUG(10,("Running [%s]\n", command));
6065
6066         /********* BEGIN SePrintOperatorPrivilege **********/
6067
6068         if ( is_print_op )
6069                 become_root();
6070
6071         ret = smbrun(command, NULL);
6072
6073         if ( is_print_op )
6074                 unbecome_root();
6075
6076         /********* END SePrintOperatorPrivilege **********/
6077
6078         DEBUGADD(10,("returned [%d]\n", ret));
6079
6080         TALLOC_FREE(command);
6081
6082         if ( ret != 0 ) {
6083                 return WERR_ACCESS_DENIED;
6084         }
6085
6086         return WERR_OK;
6087 }
6088
6089 /****************************************************************************
6090 ****************************************************************************/
6091
6092 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6093                              struct spoolss_SetPrinterInfo2 *info2,
6094                              const char *remote_machine,
6095                              struct messaging_context *msg_ctx)
6096 {
6097         char *cmd = lp_addprinter_cmd();
6098         char **qlines;
6099         char *command = NULL;
6100         int numlines;
6101         int ret;
6102         int fd;
6103         bool is_print_op = false;
6104
6105         if (!remote_machine) {
6106                 return false;
6107         }
6108
6109         command = talloc_asprintf(ctx,
6110                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6111                         cmd, info2->printername, info2->sharename,
6112                         info2->portname, info2->drivername,
6113                         info2->location, info2->comment, remote_machine);
6114         if (!command) {
6115                 return false;
6116         }
6117
6118         if ( token )
6119                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6120
6121         DEBUG(10,("Running [%s]\n", command));
6122
6123         /********* BEGIN SePrintOperatorPrivilege **********/
6124
6125         if ( is_print_op )
6126                 become_root();
6127
6128         if ( (ret = smbrun(command, &fd)) == 0 ) {
6129                 /* Tell everyone we updated smb.conf. */
6130                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6131         }
6132
6133         if ( is_print_op )
6134                 unbecome_root();
6135
6136         /********* END SePrintOperatorPrivilege **********/
6137
6138         DEBUGADD(10,("returned [%d]\n", ret));
6139
6140         TALLOC_FREE(command);
6141
6142         if ( ret != 0 ) {
6143                 if (fd != -1)
6144                         close(fd);
6145                 return false;
6146         }
6147
6148         /* reload our services immediately */
6149         become_root();
6150         reload_services(msg_ctx, -1, false);
6151         unbecome_root();
6152
6153         numlines = 0;
6154         /* Get lines and convert them back to dos-codepage */
6155         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6156         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6157         close(fd);
6158
6159         /* Set the portname to what the script says the portname should be. */
6160         /* but don't require anything to be return from the script exit a good error code */
6161
6162         if (numlines) {
6163                 /* Set the portname to what the script says the portname should be. */
6164                 info2->portname = talloc_strdup(ctx, qlines[0]);
6165                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6166         }
6167
6168         TALLOC_FREE(qlines);
6169         return true;
6170 }
6171
6172 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6173                                const struct auth_serversupplied_info *session_info,
6174                                struct messaging_context *msg_ctx,
6175                                int snum,
6176                                struct spoolss_SetPrinterInfo2 *printer,
6177                                struct spoolss_PrinterInfo2 *old_printer)
6178 {
6179         bool force_update = (old_printer == NULL);
6180         const char *dnsdomname;
6181         const char *longname;
6182         const char *uncname;
6183         const char *spooling;
6184         DATA_BLOB buffer;
6185         WERROR result = WERR_OK;
6186
6187         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6188                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6189                 winreg_set_printer_dataex(mem_ctx,
6190                                           session_info,
6191                                           msg_ctx,
6192                                           printer->sharename,
6193                                           SPOOL_DSSPOOLER_KEY,
6194                                           SPOOL_REG_DRIVERNAME,
6195                                           REG_SZ,
6196                                           buffer.data,
6197                                           buffer.length);
6198
6199                 if (!force_update) {
6200                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6201                                 printer->drivername));
6202
6203                         notify_printer_driver(server_event_context(), msg_ctx,
6204                                               snum, printer->drivername ?
6205                                               printer->drivername : "");
6206                 }
6207         }
6208
6209         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6210                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6211                 winreg_set_printer_dataex(mem_ctx,
6212                                           session_info,
6213                                           msg_ctx,
6214                                           printer->sharename,
6215                                           SPOOL_DSSPOOLER_KEY,
6216                                           SPOOL_REG_DESCRIPTION,
6217                                           REG_SZ,
6218                                           buffer.data,
6219                                           buffer.length);
6220
6221                 if (!force_update) {
6222                         notify_printer_comment(server_event_context(), msg_ctx,
6223                                                snum, printer->comment ?
6224                                                printer->comment : "");
6225                 }
6226         }
6227
6228         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6229                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6230                 winreg_set_printer_dataex(mem_ctx,
6231                                           session_info,
6232                                           msg_ctx,
6233                                           printer->sharename,
6234                                           SPOOL_DSSPOOLER_KEY,
6235                                           SPOOL_REG_PRINTSHARENAME,
6236                                           REG_SZ,
6237                                           buffer.data,
6238                                           buffer.length);
6239
6240                 if (!force_update) {
6241                         notify_printer_sharename(server_event_context(),
6242                                                  msg_ctx,
6243                                                  snum, printer->sharename ?
6244                                                  printer->sharename : "");
6245                 }
6246         }
6247
6248         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6249                 const char *p;
6250
6251                 p = strrchr(printer->printername, '\\' );
6252                 if (p != NULL) {
6253                         p++;
6254                 } else {
6255                         p = printer->printername;
6256                 }
6257
6258                 push_reg_sz(mem_ctx, &buffer, p);
6259                 winreg_set_printer_dataex(mem_ctx,
6260                                           session_info,
6261                                           msg_ctx,
6262                                           printer->sharename,
6263                                           SPOOL_DSSPOOLER_KEY,
6264                                           SPOOL_REG_PRINTERNAME,
6265                                           REG_SZ,
6266                                           buffer.data,
6267                                           buffer.length);
6268
6269                 if (!force_update) {
6270                         notify_printer_printername(server_event_context(),
6271                                                    msg_ctx, snum, p ? p : "");
6272                 }
6273         }
6274
6275         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6276                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6277                 winreg_set_printer_dataex(mem_ctx,
6278                                           session_info,
6279                                           msg_ctx,
6280                                           printer->sharename,
6281                                           SPOOL_DSSPOOLER_KEY,
6282                                           SPOOL_REG_PORTNAME,
6283                                           REG_SZ,
6284                                           buffer.data,
6285                                           buffer.length);
6286
6287                 if (!force_update) {
6288                         notify_printer_port(server_event_context(),
6289                                             msg_ctx, snum, printer->portname ?
6290                                             printer->portname : "");
6291                 }
6292         }
6293
6294         if (force_update || !strequal(printer->location, old_printer->location)) {
6295                 push_reg_sz(mem_ctx, &buffer, printer->location);
6296                 winreg_set_printer_dataex(mem_ctx,
6297                                           session_info,
6298                                           msg_ctx,
6299                                           printer->sharename,
6300                                           SPOOL_DSSPOOLER_KEY,
6301                                           SPOOL_REG_LOCATION,
6302                                           REG_SZ,
6303                                           buffer.data,
6304                                           buffer.length);
6305
6306                 if (!force_update) {
6307                         notify_printer_location(server_event_context(),
6308                                                 msg_ctx, snum,
6309                                                 printer->location ?
6310                                                 printer->location : "");
6311                 }
6312         }
6313
6314         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6315                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6316                 winreg_set_printer_dataex(mem_ctx,
6317                                           session_info,
6318                                           msg_ctx,
6319                                           printer->sharename,
6320                                           SPOOL_DSSPOOLER_KEY,
6321                                           SPOOL_REG_PRINTSEPARATORFILE,
6322                                           REG_SZ,
6323                                           buffer.data,
6324                                           buffer.length);
6325
6326                 if (!force_update) {
6327                         notify_printer_sepfile(server_event_context(),
6328                                                msg_ctx, snum,
6329                                                printer->sepfile ?
6330                                                printer->sepfile : "");
6331                 }
6332         }
6333
6334         if (force_update || printer->starttime != old_printer->starttime) {
6335                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6336                 SIVAL(buffer.data, 0, printer->starttime);
6337                 winreg_set_printer_dataex(mem_ctx,
6338                                           session_info,
6339                                           msg_ctx,
6340                                           printer->sharename,
6341                                           SPOOL_DSSPOOLER_KEY,
6342                                           SPOOL_REG_PRINTSTARTTIME,
6343                                           REG_DWORD,
6344                                           buffer.data,
6345                                           buffer.length);
6346         }
6347
6348         if (force_update || printer->untiltime != old_printer->untiltime) {
6349                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6350                 SIVAL(buffer.data, 0, printer->untiltime);
6351                 winreg_set_printer_dataex(mem_ctx,
6352                                           session_info,
6353                                           msg_ctx,
6354                                           printer->sharename,
6355                                           SPOOL_DSSPOOLER_KEY,
6356                                           SPOOL_REG_PRINTENDTIME,
6357                                           REG_DWORD,
6358                                           buffer.data,
6359                                           buffer.length);
6360         }
6361
6362         if (force_update || printer->priority != old_printer->priority) {
6363                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6364                 SIVAL(buffer.data, 0, printer->priority);
6365                 winreg_set_printer_dataex(mem_ctx,
6366                                           session_info,
6367                                           msg_ctx,
6368                                           printer->sharename,
6369                                           SPOOL_DSSPOOLER_KEY,
6370                                           SPOOL_REG_PRIORITY,
6371                                           REG_DWORD,
6372                                           buffer.data,
6373                                           buffer.length);
6374         }
6375
6376         if (force_update || printer->attributes != old_printer->attributes) {
6377                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6378                 SIVAL(buffer.data, 0, (printer->attributes &
6379                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6380                 winreg_set_printer_dataex(mem_ctx,
6381                                           session_info,
6382                                           msg_ctx,
6383                                           printer->sharename,
6384                                           SPOOL_DSSPOOLER_KEY,
6385                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6386                                           REG_DWORD,
6387                                           buffer.data,
6388                                           buffer.length);
6389
6390                 switch (printer->attributes & 0x3) {
6391                         case 0:
6392                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6393                                 break;
6394                         case 1:
6395                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6396                                 break;
6397                         case 2:
6398                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6399                                 break;
6400                         default:
6401                                 spooling = "unknown";
6402                 }
6403                 push_reg_sz(mem_ctx, &buffer, spooling);
6404                 winreg_set_printer_dataex(mem_ctx,
6405                                           session_info,
6406                                           msg_ctx,
6407                                           printer->sharename,
6408                                           SPOOL_DSSPOOLER_KEY,
6409                                           SPOOL_REG_PRINTSPOOLING,
6410                                           REG_SZ,
6411                                           buffer.data,
6412                                           buffer.length);
6413         }
6414
6415         push_reg_sz(mem_ctx, &buffer, global_myname());
6416         winreg_set_printer_dataex(mem_ctx,
6417                                   session_info,
6418                                   msg_ctx,
6419                                   printer->sharename,
6420                                   SPOOL_DSSPOOLER_KEY,
6421                                   SPOOL_REG_SHORTSERVERNAME,
6422                                   REG_SZ,
6423                                   buffer.data,
6424                                   buffer.length);
6425
6426         dnsdomname = get_mydnsfullname();
6427         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6428                 longname = talloc_strdup(mem_ctx, dnsdomname);
6429         } else {
6430                 longname = talloc_strdup(mem_ctx, global_myname());
6431         }
6432         if (longname == NULL) {
6433                 result = WERR_NOMEM;
6434                 goto done;
6435         }
6436
6437         push_reg_sz(mem_ctx, &buffer, longname);
6438         winreg_set_printer_dataex(mem_ctx,
6439                                   session_info,
6440                                   msg_ctx,
6441                                   printer->sharename,
6442                                   SPOOL_DSSPOOLER_KEY,
6443                                   SPOOL_REG_SERVERNAME,
6444                                   REG_SZ,
6445                                   buffer.data,
6446                                   buffer.length);
6447
6448         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6449                                   global_myname(), printer->sharename);
6450         push_reg_sz(mem_ctx, &buffer, uncname);
6451         winreg_set_printer_dataex(mem_ctx,
6452                                   session_info,
6453                                   msg_ctx,
6454                                   printer->sharename,
6455                                   SPOOL_DSSPOOLER_KEY,
6456                                   SPOOL_REG_UNCNAME,
6457                                   REG_SZ,
6458                                   buffer.data,
6459                                   buffer.length);
6460
6461 done:
6462         return result;
6463 }
6464
6465 /********************************************************************
6466  * Called by spoolss_api_setprinter
6467  * when updating a printer description.
6468  ********************************************************************/
6469
6470 static WERROR update_printer(struct pipes_struct *p,
6471                              struct policy_handle *handle,
6472                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6473                              struct spoolss_DeviceMode *devmode)
6474 {
6475         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6476         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6477         struct spoolss_PrinterInfo2 *old_printer;
6478         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6479         int snum;
6480         WERROR result = WERR_OK;
6481         TALLOC_CTX *tmp_ctx;
6482
6483         DEBUG(8,("update_printer\n"));
6484
6485         tmp_ctx = talloc_new(p->mem_ctx);
6486         if (tmp_ctx == NULL) {
6487                 return WERR_NOMEM;
6488         }
6489
6490         if (!Printer) {
6491                 result = WERR_BADFID;
6492                 goto done;
6493         }
6494
6495         if (!get_printer_snum(p, handle, &snum, NULL)) {
6496                 result = WERR_BADFID;
6497                 goto done;
6498         }
6499
6500         result = winreg_get_printer(tmp_ctx,
6501                                     get_session_info_system(),
6502                                     p->msg_ctx,
6503                                     lp_const_servicename(snum),
6504                                     &old_printer);
6505         if (!W_ERROR_IS_OK(result)) {
6506                 result = WERR_BADFID;
6507                 goto done;
6508         }
6509
6510         /* Do sanity check on the requested changes for Samba */
6511         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6512                 result = WERR_INVALID_PARAM;
6513                 goto done;
6514         }
6515
6516         /* FIXME!!! If the driver has changed we really should verify that
6517            it is installed before doing much else   --jerry */
6518
6519         /* Check calling user has permission to update printer description */
6520         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6521                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6522                 result = WERR_ACCESS_DENIED;
6523                 goto done;
6524         }
6525
6526         /* Call addprinter hook */
6527         /* Check changes to see if this is really needed */
6528
6529         if (*lp_addprinter_cmd() &&
6530                         (!strequal(printer->drivername, old_printer->drivername) ||
6531                          !strequal(printer->comment, old_printer->comment) ||
6532                          !strequal(printer->portname, old_printer->portname) ||
6533                          !strequal(printer->location, old_printer->location)) )
6534         {
6535                 /* add_printer_hook() will call reload_services() */
6536                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6537                                       printer, p->client_id->addr,
6538                                       p->msg_ctx)) {
6539                         result = WERR_ACCESS_DENIED;
6540                         goto done;
6541                 }
6542         }
6543
6544         update_dsspooler(tmp_ctx,
6545                          get_session_info_system(),
6546                          p->msg_ctx,
6547                          snum,
6548                          printer,
6549                          old_printer);
6550
6551         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6552
6553         if (devmode == NULL) {
6554                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6555         }
6556         result = winreg_update_printer(tmp_ctx,
6557                                        get_session_info_system(),
6558                                        p->msg_ctx,
6559                                        printer->sharename,
6560                                        printer_mask,
6561                                        printer,
6562                                        devmode,
6563                                        NULL);
6564
6565 done:
6566         talloc_free(tmp_ctx);
6567
6568         return result;
6569 }
6570
6571 /****************************************************************************
6572 ****************************************************************************/
6573 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6574                                            struct policy_handle *handle,
6575                                            struct spoolss_SetPrinterInfo7 *info7)
6576 {
6577 #ifdef HAVE_ADS
6578         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6579         WERROR result;
6580         int snum;
6581         struct printer_handle *Printer;
6582
6583         if ( lp_security() != SEC_ADS ) {
6584                 return WERR_UNKNOWN_LEVEL;
6585         }
6586
6587         Printer = find_printer_index_by_hnd(p, handle);
6588
6589         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6590
6591         if (!Printer)
6592                 return WERR_BADFID;
6593
6594         if (!get_printer_snum(p, handle, &snum, NULL))
6595                 return WERR_BADFID;
6596
6597         result = winreg_get_printer(p->mem_ctx,
6598                                     get_session_info_system(),
6599                                     p->msg_ctx,
6600                                     lp_servicename(snum),
6601                                     &pinfo2);
6602         if (!W_ERROR_IS_OK(result)) {
6603                 return WERR_BADFID;
6604         }
6605
6606         nt_printer_publish(pinfo2,
6607                            get_session_info_system(),
6608                            p->msg_ctx,
6609                            pinfo2,
6610                            info7->action);
6611
6612         TALLOC_FREE(pinfo2);
6613         return WERR_OK;
6614 #else
6615         return WERR_UNKNOWN_LEVEL;
6616 #endif
6617 }
6618
6619 /********************************************************************
6620  ********************************************************************/
6621
6622 static WERROR update_printer_devmode(struct pipes_struct *p,
6623                                      struct policy_handle *handle,
6624                                      struct spoolss_DeviceMode *devmode)
6625 {
6626         int snum;
6627         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6628         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6629
6630         DEBUG(8,("update_printer_devmode\n"));
6631
6632         if (!Printer) {
6633                 return WERR_BADFID;
6634         }
6635
6636         if (!get_printer_snum(p, handle, &snum, NULL)) {
6637                 return WERR_BADFID;
6638         }
6639
6640         /* Check calling user has permission to update printer description */
6641         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6642                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6643                 return WERR_ACCESS_DENIED;
6644         }
6645
6646         return winreg_update_printer(p->mem_ctx,
6647                                      get_session_info_system(),
6648                                      p->msg_ctx,
6649                                      lp_const_servicename(snum),
6650                                      info2_mask,
6651                                      NULL,
6652                                      devmode,
6653                                      NULL);
6654 }
6655
6656
6657 /****************************************************************
6658  _spoolss_SetPrinter
6659 ****************************************************************/
6660
6661 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6662                            struct spoolss_SetPrinter *r)
6663 {
6664         WERROR result;
6665
6666         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6667
6668         if (!Printer) {
6669                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6670                         OUR_HANDLE(r->in.handle)));
6671                 return WERR_BADFID;
6672         }
6673
6674         /* check the level */
6675         switch (r->in.info_ctr->level) {
6676                 case 0:
6677                         return control_printer(r->in.handle, r->in.command, p);
6678                 case 2:
6679                         result = update_printer(p, r->in.handle,
6680                                                 r->in.info_ctr,
6681                                                 r->in.devmode_ctr->devmode);
6682                         if (!W_ERROR_IS_OK(result))
6683                                 return result;
6684                         if (r->in.secdesc_ctr->sd)
6685                                 result = update_printer_sec(r->in.handle, p,
6686                                                             r->in.secdesc_ctr);
6687                         return result;
6688                 case 3:
6689                         return update_printer_sec(r->in.handle, p,
6690                                                   r->in.secdesc_ctr);
6691                 case 7:
6692                         return publish_or_unpublish_printer(p, r->in.handle,
6693                                                             r->in.info_ctr->info.info7);
6694                 case 8:
6695                         return update_printer_devmode(p, r->in.handle,
6696                                                       r->in.devmode_ctr->devmode);
6697                 default:
6698                         return WERR_UNKNOWN_LEVEL;
6699         }
6700 }
6701
6702 /****************************************************************
6703  _spoolss_FindClosePrinterNotify
6704 ****************************************************************/
6705
6706 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6707                                        struct spoolss_FindClosePrinterNotify *r)
6708 {
6709         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6710
6711         if (!Printer) {
6712                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6713                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6714                 return WERR_BADFID;
6715         }
6716
6717         if (Printer->notify.cli_chan != NULL &&
6718             Printer->notify.cli_chan->active_connections > 0) {
6719                 int snum = -1;
6720
6721                 if (Printer->printer_type == SPLHND_PRINTER) {
6722                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6723                                 return WERR_BADFID;
6724                         }
6725                 }
6726
6727                 srv_spoolss_replycloseprinter(snum, Printer);
6728         }
6729
6730         Printer->notify.flags=0;
6731         Printer->notify.options=0;
6732         Printer->notify.localmachine[0]='\0';
6733         Printer->notify.printerlocal=0;
6734         TALLOC_FREE(Printer->notify.option);
6735
6736         return WERR_OK;
6737 }
6738
6739 /****************************************************************
6740  _spoolss_AddJob
6741 ****************************************************************/
6742
6743 WERROR _spoolss_AddJob(struct pipes_struct *p,
6744                        struct spoolss_AddJob *r)
6745 {
6746         if (!r->in.buffer && (r->in.offered != 0)) {
6747                 return WERR_INVALID_PARAM;
6748         }
6749
6750         /* this is what a NT server returns for AddJob. AddJob must fail on
6751          * non-local printers */
6752
6753         if (r->in.level != 1) {
6754                 return WERR_UNKNOWN_LEVEL;
6755         }
6756
6757         return WERR_INVALID_PARAM;
6758 }
6759
6760 /****************************************************************************
6761 fill_job_info1
6762 ****************************************************************************/
6763
6764 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6765                              struct spoolss_JobInfo1 *r,
6766                              const print_queue_struct *queue,
6767                              int position, int snum,
6768                              struct spoolss_PrinterInfo2 *pinfo2)
6769 {
6770         struct tm *t;
6771
6772         t = gmtime(&queue->time);
6773
6774         r->job_id               = queue->job;
6775
6776         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6777         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6778         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6779         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6780         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6781         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6782         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6783         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6784         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6785         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6786         r->text_status          = talloc_strdup(mem_ctx, "");
6787         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6788
6789         r->status               = nt_printj_status(queue->status);
6790         r->priority             = queue->priority;
6791         r->position             = position;
6792         r->total_pages          = queue->page_count;
6793         r->pages_printed        = 0; /* ??? */
6794
6795         init_systemtime(&r->submitted, t);
6796
6797         return WERR_OK;
6798 }
6799
6800 /****************************************************************************
6801 fill_job_info2
6802 ****************************************************************************/
6803
6804 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6805                              struct spoolss_JobInfo2 *r,
6806                              const print_queue_struct *queue,
6807                              int position, int snum,
6808                              struct spoolss_PrinterInfo2 *pinfo2,
6809                              struct spoolss_DeviceMode *devmode)
6810 {
6811         struct tm *t;
6812
6813         t = gmtime(&queue->time);
6814
6815         r->job_id               = queue->job;
6816
6817         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6818         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6819         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6820         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6821         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6822         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6823         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6824         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6825         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6826         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6827         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6828         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6829         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6830         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6831         r->parameters           = talloc_strdup(mem_ctx, "");
6832         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6833         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6834         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6835
6836         r->devmode              = devmode;
6837
6838         r->text_status          = talloc_strdup(mem_ctx, "");
6839         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6840
6841         r->secdesc              = NULL;
6842
6843         r->status               = nt_printj_status(queue->status);
6844         r->priority             = queue->priority;
6845         r->position             = position;
6846         r->start_time           = 0;
6847         r->until_time           = 0;
6848         r->total_pages          = queue->page_count;
6849         r->size                 = queue->size;
6850         init_systemtime(&r->submitted, t);
6851         r->time                 = 0;
6852         r->pages_printed        = 0; /* ??? */
6853
6854         return WERR_OK;
6855 }
6856
6857 /****************************************************************************
6858 fill_job_info3
6859 ****************************************************************************/
6860
6861 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6862                              struct spoolss_JobInfo3 *r,
6863                              const print_queue_struct *queue,
6864                              const print_queue_struct *next_queue,
6865                              int position, int snum,
6866                              struct spoolss_PrinterInfo2 *pinfo2)
6867 {
6868         r->job_id               = queue->job;
6869         r->next_job_id          = 0;
6870         if (next_queue) {
6871                 r->next_job_id  = next_queue->job;
6872         }
6873         r->reserved             = 0;
6874
6875         return WERR_OK;
6876 }
6877
6878 /****************************************************************************
6879  Enumjobs at level 1.
6880 ****************************************************************************/
6881
6882 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6883                               const print_queue_struct *queue,
6884                               uint32_t num_queues, int snum,
6885                               struct spoolss_PrinterInfo2 *pinfo2,
6886                               union spoolss_JobInfo **info_p,
6887                               uint32_t *count)
6888 {
6889         union spoolss_JobInfo *info;
6890         int i;
6891         WERROR result = WERR_OK;
6892
6893         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6894         W_ERROR_HAVE_NO_MEMORY(info);
6895
6896         *count = num_queues;
6897
6898         for (i=0; i<*count; i++) {
6899                 result = fill_job_info1(info,
6900                                         &info[i].info1,
6901                                         &queue[i],
6902                                         i,
6903                                         snum,
6904                                         pinfo2);
6905                 if (!W_ERROR_IS_OK(result)) {
6906                         goto out;
6907                 }
6908         }
6909
6910  out:
6911         if (!W_ERROR_IS_OK(result)) {
6912                 TALLOC_FREE(info);
6913                 *count = 0;
6914                 return result;
6915         }
6916
6917         *info_p = info;
6918
6919         return WERR_OK;
6920 }
6921
6922 /****************************************************************************
6923  Enumjobs at level 2.
6924 ****************************************************************************/
6925
6926 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6927                               const print_queue_struct *queue,
6928                               uint32_t num_queues, int snum,
6929                               struct spoolss_PrinterInfo2 *pinfo2,
6930                               union spoolss_JobInfo **info_p,
6931                               uint32_t *count)
6932 {
6933         union spoolss_JobInfo *info;
6934         int i;
6935         WERROR result = WERR_OK;
6936
6937         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6938         W_ERROR_HAVE_NO_MEMORY(info);
6939
6940         *count = num_queues;
6941
6942         for (i=0; i<*count; i++) {
6943                 struct spoolss_DeviceMode *devmode;
6944
6945                 result = spoolss_create_default_devmode(info,
6946                                                         pinfo2->printername,
6947                                                         &devmode);
6948                 if (!W_ERROR_IS_OK(result)) {
6949                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6950                         goto out;
6951                 }
6952
6953                 result = fill_job_info2(info,
6954                                         &info[i].info2,
6955                                         &queue[i],
6956                                         i,
6957                                         snum,
6958                                         pinfo2,
6959                                         devmode);
6960                 if (!W_ERROR_IS_OK(result)) {
6961                         goto out;
6962                 }
6963         }
6964
6965  out:
6966         if (!W_ERROR_IS_OK(result)) {
6967                 TALLOC_FREE(info);
6968                 *count = 0;
6969                 return result;
6970         }
6971
6972         *info_p = info;
6973
6974         return WERR_OK;
6975 }
6976
6977 /****************************************************************************
6978  Enumjobs at level 3.
6979 ****************************************************************************/
6980
6981 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6982                               const print_queue_struct *queue,
6983                               uint32_t num_queues, int snum,
6984                               struct spoolss_PrinterInfo2 *pinfo2,
6985                               union spoolss_JobInfo **info_p,
6986                               uint32_t *count)
6987 {
6988         union spoolss_JobInfo *info;
6989         int i;
6990         WERROR result = WERR_OK;
6991
6992         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6993         W_ERROR_HAVE_NO_MEMORY(info);
6994
6995         *count = num_queues;
6996
6997         for (i=0; i<*count; i++) {
6998                 const print_queue_struct *next_queue = NULL;
6999
7000                 if (i+1 < *count) {
7001                         next_queue = &queue[i+1];
7002                 }
7003
7004                 result = fill_job_info3(info,
7005                                         &info[i].info3,
7006                                         &queue[i],
7007                                         next_queue,
7008                                         i,
7009                                         snum,
7010                                         pinfo2);
7011                 if (!W_ERROR_IS_OK(result)) {
7012                         goto out;
7013                 }
7014         }
7015
7016  out:
7017         if (!W_ERROR_IS_OK(result)) {
7018                 TALLOC_FREE(info);
7019                 *count = 0;
7020                 return result;
7021         }
7022
7023         *info_p = info;
7024
7025         return WERR_OK;
7026 }
7027
7028 /****************************************************************
7029  _spoolss_EnumJobs
7030 ****************************************************************/
7031
7032 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7033                          struct spoolss_EnumJobs *r)
7034 {
7035         WERROR result;
7036         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7037         int snum;
7038         print_status_struct prt_status;
7039         print_queue_struct *queue = NULL;
7040         uint32_t count;
7041
7042         /* that's an [in out] buffer */
7043
7044         if (!r->in.buffer && (r->in.offered != 0)) {
7045                 return WERR_INVALID_PARAM;
7046         }
7047
7048         DEBUG(4,("_spoolss_EnumJobs\n"));
7049
7050         *r->out.needed = 0;
7051         *r->out.count = 0;
7052         *r->out.info = NULL;
7053
7054         /* lookup the printer snum and tdb entry */
7055
7056         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7057                 return WERR_BADFID;
7058         }
7059
7060         result = winreg_get_printer(p->mem_ctx,
7061                                     get_session_info_system(),
7062                                     p->msg_ctx,
7063                                     lp_const_servicename(snum),
7064                                     &pinfo2);
7065         if (!W_ERROR_IS_OK(result)) {
7066                 return result;
7067         }
7068
7069         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7070         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7071                 count, prt_status.status, prt_status.message));
7072
7073         if (count == 0) {
7074                 SAFE_FREE(queue);
7075                 TALLOC_FREE(pinfo2);
7076                 return WERR_OK;
7077         }
7078
7079         switch (r->in.level) {
7080         case 1:
7081                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7082                                          pinfo2, r->out.info, r->out.count);
7083                 break;
7084         case 2:
7085                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7086                                          pinfo2, r->out.info, r->out.count);
7087                 break;
7088         case 3:
7089                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7090                                          pinfo2, r->out.info, r->out.count);
7091                 break;
7092         default:
7093                 result = WERR_UNKNOWN_LEVEL;
7094                 break;
7095         }
7096
7097         SAFE_FREE(queue);
7098         TALLOC_FREE(pinfo2);
7099
7100         if (!W_ERROR_IS_OK(result)) {
7101                 return result;
7102         }
7103
7104         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7105                                                      spoolss_EnumJobs,
7106                                                      *r->out.info, r->in.level,
7107                                                      *r->out.count);
7108         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7109         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7110
7111         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7112 }
7113
7114 /****************************************************************
7115  _spoolss_ScheduleJob
7116 ****************************************************************/
7117
7118 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7119                             struct spoolss_ScheduleJob *r)
7120 {
7121         return WERR_OK;
7122 }
7123
7124 /****************************************************************
7125 ****************************************************************/
7126
7127 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7128                                struct messaging_context *msg_ctx,
7129                                const char *printer_name,
7130                                uint32_t job_id,
7131                                struct spoolss_SetJobInfo1 *r)
7132 {
7133         char *old_doc_name;
7134
7135         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7136                 return WERR_BADFID;
7137         }
7138
7139         if (strequal(old_doc_name, r->document_name)) {
7140                 return WERR_OK;
7141         }
7142
7143         if (!print_job_set_name(server_event_context(), msg_ctx,
7144                                 printer_name, job_id, r->document_name)) {
7145                 return WERR_BADFID;
7146         }
7147
7148         return WERR_OK;
7149 }
7150
7151 /****************************************************************
7152  _spoolss_SetJob
7153 ****************************************************************/
7154
7155 WERROR _spoolss_SetJob(struct pipes_struct *p,
7156                        struct spoolss_SetJob *r)
7157 {
7158         const struct auth_serversupplied_info *session_info = p->session_info;
7159         int snum;
7160         WERROR errcode = WERR_BADFUNC;
7161
7162         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7163                 return WERR_BADFID;
7164         }
7165
7166         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7167                 return WERR_INVALID_PRINTER_NAME;
7168         }
7169
7170         switch (r->in.command) {
7171         case SPOOLSS_JOB_CONTROL_CANCEL:
7172         case SPOOLSS_JOB_CONTROL_DELETE:
7173                 errcode = print_job_delete(session_info, p->msg_ctx,
7174                                            snum, r->in.job_id);
7175                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7176                         errcode = WERR_OK;
7177                 }
7178                 break;
7179         case SPOOLSS_JOB_CONTROL_PAUSE:
7180                 if (print_job_pause(session_info, p->msg_ctx,
7181                                     snum, r->in.job_id, &errcode)) {
7182                         errcode = WERR_OK;
7183                 }
7184                 break;
7185         case SPOOLSS_JOB_CONTROL_RESTART:
7186         case SPOOLSS_JOB_CONTROL_RESUME:
7187                 if (print_job_resume(session_info, p->msg_ctx,
7188                                      snum, r->in.job_id, &errcode)) {
7189                         errcode = WERR_OK;
7190                 }
7191                 break;
7192         case 0:
7193                 errcode = WERR_OK;
7194                 break;
7195         default:
7196                 return WERR_UNKNOWN_LEVEL;
7197         }
7198
7199         if (!W_ERROR_IS_OK(errcode)) {
7200                 return errcode;
7201         }
7202
7203         if (r->in.ctr == NULL) {
7204                 return errcode;
7205         }
7206
7207         switch (r->in.ctr->level) {
7208         case 1:
7209                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7210                                            lp_const_servicename(snum),
7211                                            r->in.job_id,
7212                                            r->in.ctr->info.info1);
7213                 break;
7214         case 2:
7215         case 3:
7216         case 4:
7217         default:
7218                 return WERR_UNKNOWN_LEVEL;
7219         }
7220
7221         return errcode;
7222 }
7223
7224 /****************************************************************************
7225  Enumerates all printer drivers by level and architecture.
7226 ****************************************************************************/
7227
7228 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7229                                                        const struct auth_serversupplied_info *session_info,
7230                                                        struct messaging_context *msg_ctx,
7231                                                        const char *servername,
7232                                                        const char *architecture,
7233                                                        uint32_t level,
7234                                                        union spoolss_DriverInfo **info_p,
7235                                                        uint32_t *count_p)
7236 {
7237         int i;
7238         uint32_t version;
7239         struct spoolss_DriverInfo8 *driver;
7240         union spoolss_DriverInfo *info = NULL;
7241         uint32_t count = 0;
7242         WERROR result = WERR_OK;
7243         uint32_t num_drivers;
7244         const char **drivers;
7245
7246         *count_p = 0;
7247         *info_p = NULL;
7248
7249         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7250                 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7251                                                 architecture, version,
7252                                                 &num_drivers, &drivers);
7253                 if (!W_ERROR_IS_OK(result)) {
7254                         goto out;
7255                 }
7256                 DEBUG(4, ("we have:[%d] drivers in environment"
7257                           " [%s] and version [%d]\n",
7258                           num_drivers, architecture, version));
7259
7260                 if (num_drivers != 0) {
7261                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7262                                                     union spoolss_DriverInfo,
7263                                                     count + num_drivers);
7264                         if (!info) {
7265                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7266                                         "failed to enlarge driver info buffer!\n"));
7267                                 result = WERR_NOMEM;
7268                                 goto out;
7269                         }
7270                 }
7271
7272                 for (i = 0; i < num_drivers; i++) {
7273                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7274
7275                         result = winreg_get_driver(mem_ctx, session_info,
7276                                                    msg_ctx,
7277                                                    architecture, drivers[i],
7278                                                    version, &driver);
7279                         if (!W_ERROR_IS_OK(result)) {
7280                                 goto out;
7281                         }
7282
7283                         switch (level) {
7284                         case 1:
7285                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7286                                                                    driver, servername);
7287                                 break;
7288                         case 2:
7289                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7290                                                                    driver, servername);
7291                                 break;
7292                         case 3:
7293                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7294                                                                    driver, servername);
7295                                 break;
7296                         case 4:
7297                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7298                                                                    driver, servername);
7299                                 break;
7300                         case 5:
7301                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7302                                                                    driver, servername);
7303                                 break;
7304                         case 6:
7305                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7306                                                                    driver, servername);
7307                                 break;
7308                         case 8:
7309                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7310                                                                    driver, servername);
7311                                 break;
7312                         default:
7313                                 result = WERR_UNKNOWN_LEVEL;
7314                                 break;
7315                         }
7316
7317                         TALLOC_FREE(driver);
7318
7319                         if (!W_ERROR_IS_OK(result)) {
7320                                 goto out;
7321                         }
7322                 }
7323
7324                 count += num_drivers;
7325                 TALLOC_FREE(drivers);
7326         }
7327
7328  out:
7329         TALLOC_FREE(drivers);
7330
7331         if (!W_ERROR_IS_OK(result)) {
7332                 TALLOC_FREE(info);
7333                 return result;
7334         }
7335
7336         *info_p = info;
7337         *count_p = count;
7338
7339         return WERR_OK;
7340 }
7341
7342 /****************************************************************************
7343  Enumerates all printer drivers by level.
7344 ****************************************************************************/
7345
7346 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7347                                        const struct auth_serversupplied_info *session_info,
7348                                        struct messaging_context *msg_ctx,
7349                                        const char *servername,
7350                                        const char *architecture,
7351                                        uint32_t level,
7352                                        union spoolss_DriverInfo **info_p,
7353                                        uint32_t *count_p)
7354 {
7355         uint32_t a,i;
7356         WERROR result = WERR_OK;
7357
7358         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7359
7360                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7361
7362                         union spoolss_DriverInfo *info = NULL;
7363                         uint32_t count = 0;
7364
7365                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7366                                                                           session_info,
7367                                                                           msg_ctx,
7368                                                                           servername,
7369                                                                           archi_table[a].long_archi,
7370                                                                           level,
7371                                                                           &info,
7372                                                                           &count);
7373                         if (!W_ERROR_IS_OK(result)) {
7374                                 continue;
7375                         }
7376
7377                         for (i=0; i < count; i++) {
7378                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7379                                              info[i], info_p, count_p);
7380                         }
7381                 }
7382
7383                 return result;
7384         }
7385
7386         return enumprinterdrivers_level_by_architecture(mem_ctx,
7387                                                         session_info,
7388                                                         msg_ctx,
7389                                                         servername,
7390                                                         architecture,
7391                                                         level,
7392                                                         info_p,
7393                                                         count_p);
7394 }
7395
7396 /****************************************************************
7397  _spoolss_EnumPrinterDrivers
7398 ****************************************************************/
7399
7400 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7401                                    struct spoolss_EnumPrinterDrivers *r)
7402 {
7403         const char *cservername;
7404         WERROR result;
7405
7406         /* that's an [in out] buffer */
7407
7408         if (!r->in.buffer && (r->in.offered != 0)) {
7409                 return WERR_INVALID_PARAM;
7410         }
7411
7412         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7413
7414         *r->out.needed = 0;
7415         *r->out.count = 0;
7416         *r->out.info = NULL;
7417
7418         cservername = canon_servername(r->in.server);
7419
7420         if (!is_myname_or_ipaddr(cservername)) {
7421                 return WERR_UNKNOWN_PRINTER_DRIVER;
7422         }
7423
7424         result = enumprinterdrivers_level(p->mem_ctx,
7425                                           get_session_info_system(),
7426                                           p->msg_ctx,
7427                                           cservername,
7428                                           r->in.environment,
7429                                           r->in.level,
7430                                           r->out.info,
7431                                           r->out.count);
7432         if (!W_ERROR_IS_OK(result)) {
7433                 return result;
7434         }
7435
7436         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7437                                                      spoolss_EnumPrinterDrivers,
7438                                                      *r->out.info, r->in.level,
7439                                                      *r->out.count);
7440         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7441         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7442
7443         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7444 }
7445
7446 /****************************************************************
7447  _spoolss_EnumForms
7448 ****************************************************************/
7449
7450 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7451                           struct spoolss_EnumForms *r)
7452 {
7453         WERROR result;
7454
7455         *r->out.count = 0;
7456         *r->out.needed = 0;
7457         *r->out.info = NULL;
7458
7459         /* that's an [in out] buffer */
7460
7461         if (!r->in.buffer && (r->in.offered != 0) ) {
7462                 return WERR_INVALID_PARAM;
7463         }
7464
7465         DEBUG(4,("_spoolss_EnumForms\n"));
7466         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7467         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7468
7469         switch (r->in.level) {
7470         case 1:
7471                 result = winreg_printer_enumforms1(p->mem_ctx,
7472                                                    get_session_info_system(),
7473                                                    p->msg_ctx,
7474                                                    r->out.count,
7475                                                    r->out.info);
7476                 break;
7477         default:
7478                 result = WERR_UNKNOWN_LEVEL;
7479                 break;
7480         }
7481
7482         if (!W_ERROR_IS_OK(result)) {
7483                 return result;
7484         }
7485
7486         if (*r->out.count == 0) {
7487                 return WERR_NO_MORE_ITEMS;
7488         }
7489
7490         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7491                                                      spoolss_EnumForms,
7492                                                      *r->out.info, r->in.level,
7493                                                      *r->out.count);
7494         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7495         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7496
7497         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7498 }
7499
7500 /****************************************************************
7501  _spoolss_GetForm
7502 ****************************************************************/
7503
7504 WERROR _spoolss_GetForm(struct pipes_struct *p,
7505                         struct spoolss_GetForm *r)
7506 {
7507         WERROR result;
7508
7509         /* that's an [in out] buffer */
7510
7511         if (!r->in.buffer && (r->in.offered != 0)) {
7512                 return WERR_INVALID_PARAM;
7513         }
7514
7515         DEBUG(4,("_spoolss_GetForm\n"));
7516         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7517         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7518
7519         switch (r->in.level) {
7520         case 1:
7521                 result = winreg_printer_getform1(p->mem_ctx,
7522                                                  get_session_info_system(),
7523                                                  p->msg_ctx,
7524                                                  r->in.form_name,
7525                                                  &r->out.info->info1);
7526                 break;
7527         default:
7528                 result = WERR_UNKNOWN_LEVEL;
7529                 break;
7530         }
7531
7532         if (!W_ERROR_IS_OK(result)) {
7533                 TALLOC_FREE(r->out.info);
7534                 return result;
7535         }
7536
7537         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7538                                                r->out.info, r->in.level);
7539         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7540
7541         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7542 }
7543
7544 /****************************************************************************
7545 ****************************************************************************/
7546
7547 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7548                           struct spoolss_PortInfo1 *r,
7549                           const char *name)
7550 {
7551         r->port_name = talloc_strdup(mem_ctx, name);
7552         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7553
7554         return WERR_OK;
7555 }
7556
7557 /****************************************************************************
7558  TODO: This probably needs distinguish between TCP/IP and Local ports
7559  somehow.
7560 ****************************************************************************/
7561
7562 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7563                           struct spoolss_PortInfo2 *r,
7564                           const char *name)
7565 {
7566         r->port_name = talloc_strdup(mem_ctx, name);
7567         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7568
7569         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7570         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7571
7572         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7573         W_ERROR_HAVE_NO_MEMORY(r->description);
7574
7575         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7576         r->reserved = 0;
7577
7578         return WERR_OK;
7579 }
7580
7581
7582 /****************************************************************************
7583  wrapper around the enumer ports command
7584 ****************************************************************************/
7585
7586 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7587 {
7588         char *cmd = lp_enumports_cmd();
7589         char **qlines = NULL;
7590         char *command = NULL;
7591         int numlines;
7592         int ret;
7593         int fd;
7594
7595         *count = 0;
7596         *lines = NULL;
7597
7598         /* if no hook then just fill in the default port */
7599
7600         if ( !*cmd ) {
7601                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7602                         return WERR_NOMEM;
7603                 }
7604                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7605                         TALLOC_FREE(qlines);
7606                         return WERR_NOMEM;
7607                 }
7608                 qlines[1] = NULL;
7609                 numlines = 1;
7610         }
7611         else {
7612                 /* we have a valid enumport command */
7613
7614                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7615                 if (!command) {
7616                         return WERR_NOMEM;
7617                 }
7618
7619                 DEBUG(10,("Running [%s]\n", command));
7620                 ret = smbrun(command, &fd);
7621                 DEBUG(10,("Returned [%d]\n", ret));
7622                 TALLOC_FREE(command);
7623                 if (ret != 0) {
7624                         if (fd != -1) {
7625                                 close(fd);
7626                         }
7627                         return WERR_ACCESS_DENIED;
7628                 }
7629
7630                 numlines = 0;
7631                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7632                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7633                 close(fd);
7634         }
7635
7636         *count = numlines;
7637         *lines = qlines;
7638
7639         return WERR_OK;
7640 }
7641
7642 /****************************************************************************
7643  enumports level 1.
7644 ****************************************************************************/
7645
7646 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7647                                 union spoolss_PortInfo **info_p,
7648                                 uint32_t *count)
7649 {
7650         union spoolss_PortInfo *info = NULL;
7651         int i=0;
7652         WERROR result = WERR_OK;
7653         char **qlines = NULL;
7654         int numlines = 0;
7655
7656         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7657         if (!W_ERROR_IS_OK(result)) {
7658                 goto out;
7659         }
7660
7661         if (numlines) {
7662                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7663                 if (!info) {
7664                         DEBUG(10,("Returning WERR_NOMEM\n"));
7665                         result = WERR_NOMEM;
7666                         goto out;
7667                 }
7668
7669                 for (i=0; i<numlines; i++) {
7670                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7671                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7672                         if (!W_ERROR_IS_OK(result)) {
7673                                 goto out;
7674                         }
7675                 }
7676         }
7677         TALLOC_FREE(qlines);
7678
7679 out:
7680         if (!W_ERROR_IS_OK(result)) {
7681                 TALLOC_FREE(info);
7682                 TALLOC_FREE(qlines);
7683                 *count = 0;
7684                 *info_p = NULL;
7685                 return result;
7686         }
7687
7688         *info_p = info;
7689         *count = numlines;
7690
7691         return WERR_OK;
7692 }
7693
7694 /****************************************************************************
7695  enumports level 2.
7696 ****************************************************************************/
7697
7698 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7699                                 union spoolss_PortInfo **info_p,
7700                                 uint32_t *count)
7701 {
7702         union spoolss_PortInfo *info = NULL;
7703         int i=0;
7704         WERROR result = WERR_OK;
7705         char **qlines = NULL;
7706         int numlines = 0;
7707
7708         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7709         if (!W_ERROR_IS_OK(result)) {
7710                 goto out;
7711         }
7712
7713         if (numlines) {
7714                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7715                 if (!info) {
7716                         DEBUG(10,("Returning WERR_NOMEM\n"));
7717                         result = WERR_NOMEM;
7718                         goto out;
7719                 }
7720
7721                 for (i=0; i<numlines; i++) {
7722                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7723                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7724                         if (!W_ERROR_IS_OK(result)) {
7725                                 goto out;
7726                         }
7727                 }
7728         }
7729         TALLOC_FREE(qlines);
7730
7731 out:
7732         if (!W_ERROR_IS_OK(result)) {
7733                 TALLOC_FREE(info);
7734                 TALLOC_FREE(qlines);
7735                 *count = 0;
7736                 *info_p = NULL;
7737                 return result;
7738         }
7739
7740         *info_p = info;
7741         *count = numlines;
7742
7743         return WERR_OK;
7744 }
7745
7746 /****************************************************************
7747  _spoolss_EnumPorts
7748 ****************************************************************/
7749
7750 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7751                           struct spoolss_EnumPorts *r)
7752 {
7753         WERROR result;
7754
7755         /* that's an [in out] buffer */
7756
7757         if (!r->in.buffer && (r->in.offered != 0)) {
7758                 return WERR_INVALID_PARAM;
7759         }
7760
7761         DEBUG(4,("_spoolss_EnumPorts\n"));
7762
7763         *r->out.count = 0;
7764         *r->out.needed = 0;
7765         *r->out.info = NULL;
7766
7767         switch (r->in.level) {
7768         case 1:
7769                 result = enumports_level_1(p->mem_ctx, r->out.info,
7770                                            r->out.count);
7771                 break;
7772         case 2:
7773                 result = enumports_level_2(p->mem_ctx, r->out.info,
7774                                            r->out.count);
7775                 break;
7776         default:
7777                 return WERR_UNKNOWN_LEVEL;
7778         }
7779
7780         if (!W_ERROR_IS_OK(result)) {
7781                 return result;
7782         }
7783
7784         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7785                                                      spoolss_EnumPorts,
7786                                                      *r->out.info, r->in.level,
7787                                                      *r->out.count);
7788         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7789         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7790
7791         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7792 }
7793
7794 /****************************************************************************
7795 ****************************************************************************/
7796
7797 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7798                                            const char *server,
7799                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7800                                            struct spoolss_DeviceMode *devmode,
7801                                            struct security_descriptor *secdesc,
7802                                            struct spoolss_UserLevelCtr *user_ctr,
7803                                            struct policy_handle *handle)
7804 {
7805         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7806         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7807         int     snum;
7808         WERROR err = WERR_OK;
7809
7810         /* samba does not have a concept of local, non-shared printers yet, so
7811          * make sure we always setup sharename - gd */
7812         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7813             (info2->printername != NULL && info2->printername[0] != '\0')) {
7814                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7815                         "no sharename has been set, setting printername %s as sharename\n",
7816                         info2->printername));
7817                 info2->sharename = info2->printername;
7818         }
7819
7820         /* check to see if the printer already exists */
7821         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7822                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7823                         info2->sharename));
7824                 return WERR_PRINTER_ALREADY_EXISTS;
7825         }
7826
7827         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7828                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7829                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7830                                 info2->printername));
7831                         return WERR_PRINTER_ALREADY_EXISTS;
7832                 }
7833         }
7834
7835         /* validate printer info struct */
7836         if (!info2->printername || strlen(info2->printername) == 0) {
7837                 return WERR_INVALID_PRINTER_NAME;
7838         }
7839         if (!info2->portname || strlen(info2->portname) == 0) {
7840                 return WERR_UNKNOWN_PORT;
7841         }
7842         if (!info2->drivername || strlen(info2->drivername) == 0) {
7843                 return WERR_UNKNOWN_PRINTER_DRIVER;
7844         }
7845         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7846                 return WERR_UNKNOWN_PRINTPROCESSOR;
7847         }
7848
7849         /* FIXME!!!  smbd should check to see if the driver is installed before
7850            trying to add a printer like this  --jerry */
7851
7852         if (*lp_addprinter_cmd() ) {
7853                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7854                                        info2, p->client_id->addr,
7855                                        p->msg_ctx) ) {
7856                         return WERR_ACCESS_DENIED;
7857                 }
7858         } else {
7859                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7860                         "smb.conf parameter \"addprinter command\" is defined. This"
7861                         "parameter must exist for this call to succeed\n",
7862                         info2->sharename ));
7863         }
7864
7865         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7866                 return WERR_ACCESS_DENIED;
7867         }
7868
7869         /* you must be a printer admin to add a new printer */
7870         if (!print_access_check(p->session_info,
7871                                 p->msg_ctx,
7872                                 snum,
7873                                 PRINTER_ACCESS_ADMINISTER)) {
7874                 return WERR_ACCESS_DENIED;
7875         }
7876
7877         /*
7878          * Do sanity check on the requested changes for Samba.
7879          */
7880
7881         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7882                 return WERR_INVALID_PARAM;
7883         }
7884
7885         if (devmode == NULL) {
7886                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7887         }
7888
7889         update_dsspooler(p->mem_ctx,
7890                          get_session_info_system(),
7891                          p->msg_ctx,
7892                          0,
7893                          info2,
7894                          NULL);
7895
7896         err = winreg_update_printer(p->mem_ctx,
7897                                     get_session_info_system(),
7898                                     p->msg_ctx,
7899                                     info2->sharename,
7900                                     info2_mask,
7901                                     info2,
7902                                     devmode,
7903                                     secdesc);
7904         if (!W_ERROR_IS_OK(err)) {
7905                 return err;
7906         }
7907
7908         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7909         if (!W_ERROR_IS_OK(err)) {
7910                 /* Handle open failed - remove addition. */
7911                 ZERO_STRUCTP(handle);
7912                 return err;
7913         }
7914
7915         return WERR_OK;
7916 }
7917
7918 /****************************************************************
7919  _spoolss_AddPrinterEx
7920 ****************************************************************/
7921
7922 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7923                              struct spoolss_AddPrinterEx *r)
7924 {
7925         switch (r->in.info_ctr->level) {
7926         case 1:
7927                 /* we don't handle yet */
7928                 /* but I know what to do ... */
7929                 return WERR_UNKNOWN_LEVEL;
7930         case 2:
7931                 return spoolss_addprinterex_level_2(p, r->in.server,
7932                                                     r->in.info_ctr,
7933                                                     r->in.devmode_ctr->devmode,
7934                                                     r->in.secdesc_ctr->sd,
7935                                                     r->in.userlevel_ctr,
7936                                                     r->out.handle);
7937         default:
7938                 return WERR_UNKNOWN_LEVEL;
7939         }
7940 }
7941
7942 /****************************************************************
7943  _spoolss_AddPrinter
7944 ****************************************************************/
7945
7946 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7947                            struct spoolss_AddPrinter *r)
7948 {
7949         struct spoolss_AddPrinterEx a;
7950         struct spoolss_UserLevelCtr userlevel_ctr;
7951
7952         ZERO_STRUCT(userlevel_ctr);
7953
7954         userlevel_ctr.level = 1;
7955
7956         a.in.server             = r->in.server;
7957         a.in.info_ctr           = r->in.info_ctr;
7958         a.in.devmode_ctr        = r->in.devmode_ctr;
7959         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7960         a.in.userlevel_ctr      = &userlevel_ctr;
7961         a.out.handle            = r->out.handle;
7962
7963         return _spoolss_AddPrinterEx(p, &a);
7964 }
7965
7966 /****************************************************************
7967  _spoolss_AddPrinterDriverEx
7968 ****************************************************************/
7969
7970 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7971                                    struct spoolss_AddPrinterDriverEx *r)
7972 {
7973         WERROR err = WERR_OK;
7974         const char *driver_name = NULL;
7975         uint32_t version;
7976         const char *fn;
7977
7978         switch (p->opnum) {
7979                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7980                         fn = "_spoolss_AddPrinterDriver";
7981                         break;
7982                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7983                         fn = "_spoolss_AddPrinterDriverEx";
7984                         break;
7985                 default:
7986                         return WERR_INVALID_PARAM;
7987         }
7988
7989         /*
7990          * we only support the semantics of AddPrinterDriver()
7991          * i.e. only copy files that are newer than existing ones
7992          */
7993
7994         if (r->in.flags == 0) {
7995                 return WERR_INVALID_PARAM;
7996         }
7997
7998         if (r->in.flags != APD_COPY_NEW_FILES) {
7999                 return WERR_ACCESS_DENIED;
8000         }
8001
8002         /* FIXME */
8003         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8004                 /* Clever hack from Martin Zielinski <mz@seh.de>
8005                  * to allow downgrade from level 8 (Vista).
8006                  */
8007                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8008                         r->in.info_ctr->level));
8009                 return WERR_UNKNOWN_LEVEL;
8010         }
8011
8012         DEBUG(5,("Cleaning driver's information\n"));
8013         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8014         if (!W_ERROR_IS_OK(err))
8015                 goto done;
8016
8017         DEBUG(5,("Moving driver to final destination\n"));
8018         err = move_driver_to_download_area(p, r->in.info_ctr);
8019         if (!W_ERROR_IS_OK(err)) {
8020                 goto done;
8021         }
8022
8023         err = winreg_add_driver(p->mem_ctx,
8024                                 get_session_info_system(),
8025                                 p->msg_ctx,
8026                                 r->in.info_ctr,
8027                                 &driver_name,
8028                                 &version);
8029         if (!W_ERROR_IS_OK(err)) {
8030                 goto done;
8031         }
8032
8033         /*
8034          * I think this is where he DrvUpgradePrinter() hook would be
8035          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8036          * server.  Right now, we just need to send ourselves a message
8037          * to update each printer bound to this driver.   --jerry
8038          */
8039
8040         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8041                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8042                         fn, driver_name));
8043         }
8044
8045 done:
8046         return err;
8047 }
8048
8049 /****************************************************************
8050  _spoolss_AddPrinterDriver
8051 ****************************************************************/
8052
8053 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8054                                  struct spoolss_AddPrinterDriver *r)
8055 {
8056         struct spoolss_AddPrinterDriverEx a;
8057
8058         switch (r->in.info_ctr->level) {
8059         case 2:
8060         case 3:
8061         case 4:
8062         case 5:
8063                 break;
8064         default:
8065                 return WERR_UNKNOWN_LEVEL;
8066         }
8067
8068         a.in.servername         = r->in.servername;
8069         a.in.info_ctr           = r->in.info_ctr;
8070         a.in.flags              = APD_COPY_NEW_FILES;
8071
8072         return _spoolss_AddPrinterDriverEx(p, &a);
8073 }
8074
8075 /****************************************************************************
8076 ****************************************************************************/
8077
8078 struct _spoolss_paths {
8079         int type;
8080         const char *share;
8081         const char *dir;
8082 };
8083
8084 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8085
8086 static const struct _spoolss_paths spoolss_paths[]= {
8087         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8088         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8089 };
8090
8091 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8092                                           const char *servername,
8093                                           const char *environment,
8094                                           int component,
8095                                           char **path)
8096 {
8097         const char *pservername = NULL;
8098         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8099         const char *short_archi;
8100
8101         *path = NULL;
8102
8103         /* environment may be empty */
8104         if (environment && strlen(environment)) {
8105                 long_archi = environment;
8106         }
8107
8108         /* servername may be empty */
8109         if (servername && strlen(servername)) {
8110                 pservername = canon_servername(servername);
8111
8112                 if (!is_myname_or_ipaddr(pservername)) {
8113                         return WERR_INVALID_PARAM;
8114                 }
8115         }
8116
8117         if (!(short_archi = get_short_archi(long_archi))) {
8118                 return WERR_INVALID_ENVIRONMENT;
8119         }
8120
8121         switch (component) {
8122         case SPOOLSS_PRTPROCS_PATH:
8123         case SPOOLSS_DRIVER_PATH:
8124                 if (pservername) {
8125                         *path = talloc_asprintf(mem_ctx,
8126                                         "\\\\%s\\%s\\%s",
8127                                         pservername,
8128                                         spoolss_paths[component].share,
8129                                         short_archi);
8130                 } else {
8131                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8132                                         SPOOLSS_DEFAULT_SERVER_PATH,
8133                                         spoolss_paths[component].dir,
8134                                         short_archi);
8135                 }
8136                 break;
8137         default:
8138                 return WERR_INVALID_PARAM;
8139         }
8140
8141         if (!*path) {
8142                 return WERR_NOMEM;
8143         }
8144
8145         return WERR_OK;
8146 }
8147
8148 /****************************************************************************
8149 ****************************************************************************/
8150
8151 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8152                                           const char *servername,
8153                                           const char *environment,
8154                                           struct spoolss_DriverDirectoryInfo1 *r)
8155 {
8156         WERROR werr;
8157         char *path = NULL;
8158
8159         werr = compose_spoolss_server_path(mem_ctx,
8160                                            servername,
8161                                            environment,
8162                                            SPOOLSS_DRIVER_PATH,
8163                                            &path);
8164         if (!W_ERROR_IS_OK(werr)) {
8165                 return werr;
8166         }
8167
8168         DEBUG(4,("printer driver directory: [%s]\n", path));
8169
8170         r->directory_name = path;
8171
8172         return WERR_OK;
8173 }
8174
8175 /****************************************************************
8176  _spoolss_GetPrinterDriverDirectory
8177 ****************************************************************/
8178
8179 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8180                                           struct spoolss_GetPrinterDriverDirectory *r)
8181 {
8182         WERROR werror;
8183
8184         /* that's an [in out] buffer */
8185
8186         if (!r->in.buffer && (r->in.offered != 0)) {
8187                 return WERR_INVALID_PARAM;
8188         }
8189
8190         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8191                 r->in.level));
8192
8193         *r->out.needed = 0;
8194
8195         /* r->in.level is ignored */
8196
8197         werror = getprinterdriverdir_level_1(p->mem_ctx,
8198                                              r->in.server,
8199                                              r->in.environment,
8200                                              &r->out.info->info1);
8201         if (!W_ERROR_IS_OK(werror)) {
8202                 TALLOC_FREE(r->out.info);
8203                 return werror;
8204         }
8205
8206         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8207                                                r->out.info, r->in.level);
8208         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8209
8210         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8211 }
8212
8213 /****************************************************************
8214  _spoolss_EnumPrinterData
8215 ****************************************************************/
8216
8217 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8218                                 struct spoolss_EnumPrinterData *r)
8219 {
8220         WERROR result;
8221         struct spoolss_EnumPrinterDataEx r2;
8222         uint32_t count;
8223         struct spoolss_PrinterEnumValues *info, *val = NULL;
8224         uint32_t needed;
8225
8226         r2.in.handle    = r->in.handle;
8227         r2.in.key_name  = "PrinterDriverData";
8228         r2.in.offered   = 0;
8229         r2.out.count    = &count;
8230         r2.out.info     = &info;
8231         r2.out.needed   = &needed;
8232
8233         result = _spoolss_EnumPrinterDataEx(p, &r2);
8234         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8235                 r2.in.offered = needed;
8236                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8237         }
8238         if (!W_ERROR_IS_OK(result)) {
8239                 return result;
8240         }
8241
8242         /*
8243          * The NT machine wants to know the biggest size of value and data
8244          *
8245          * cf: MSDN EnumPrinterData remark section
8246          */
8247
8248         if (!r->in.value_offered && !r->in.data_offered) {
8249                 uint32_t biggest_valuesize = 0;
8250                 uint32_t biggest_datasize = 0;
8251                 int i, name_length;
8252
8253                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8254
8255                 for (i=0; i<count; i++) {
8256
8257                         name_length = strlen(info[i].value_name);
8258                         if (strlen(info[i].value_name) > biggest_valuesize) {
8259                                 biggest_valuesize = name_length;
8260                         }
8261
8262                         if (info[i].data_length > biggest_datasize) {
8263                                 biggest_datasize = info[i].data_length;
8264                         }
8265
8266                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8267                                 biggest_datasize));
8268                 }
8269
8270                 /* the value is an UNICODE string but real_value_size is the length
8271                    in bytes including the trailing 0 */
8272
8273                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8274                 *r->out.data_needed  = biggest_datasize;
8275
8276                 DEBUG(6,("final values: [%d], [%d]\n",
8277                         *r->out.value_needed, *r->out.data_needed));
8278
8279                 return WERR_OK;
8280         }
8281
8282         if (r->in.enum_index < count) {
8283                 val = &info[r->in.enum_index];
8284         }
8285
8286         if (val == NULL) {
8287                 /* out_value should default to "" or else NT4 has
8288                    problems unmarshalling the response */
8289
8290                 if (r->in.value_offered) {
8291                         *r->out.value_needed = 1;
8292                         r->out.value_name = talloc_strdup(r, "");
8293                         if (!r->out.value_name) {
8294                                 return WERR_NOMEM;
8295                         }
8296                 } else {
8297                         r->out.value_name = NULL;
8298                         *r->out.value_needed = 0;
8299                 }
8300
8301                 /* the data is counted in bytes */
8302
8303                 *r->out.data_needed = r->in.data_offered;
8304
8305                 result = WERR_NO_MORE_ITEMS;
8306         } else {
8307                 /*
8308                  * the value is:
8309                  * - counted in bytes in the request
8310                  * - counted in UNICODE chars in the max reply
8311                  * - counted in bytes in the real size
8312                  *
8313                  * take a pause *before* coding not *during* coding
8314                  */
8315
8316                 /* name */
8317                 if (r->in.value_offered) {
8318                         r->out.value_name = talloc_strdup(r, val->value_name);
8319                         if (!r->out.value_name) {
8320                                 return WERR_NOMEM;
8321                         }
8322                         *r->out.value_needed = val->value_name_len;
8323                 } else {
8324                         r->out.value_name = NULL;
8325                         *r->out.value_needed = 0;
8326                 }
8327
8328                 /* type */
8329
8330                 *r->out.type = val->type;
8331
8332                 /* data - counted in bytes */
8333
8334                 /*
8335                  * See the section "Dynamically Typed Query Parameters"
8336                  * in MS-RPRN.
8337                  */
8338
8339                 if (r->out.data && val->data && val->data->data &&
8340                                 val->data_length && r->in.data_offered) {
8341                         memcpy(r->out.data, val->data->data,
8342                                 MIN(val->data_length,r->in.data_offered));
8343                 }
8344
8345                 *r->out.data_needed = val->data_length;
8346
8347                 result = WERR_OK;
8348         }
8349
8350         return result;
8351 }
8352
8353 /****************************************************************
8354  _spoolss_SetPrinterData
8355 ****************************************************************/
8356
8357 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8358                                struct spoolss_SetPrinterData *r)
8359 {
8360         struct spoolss_SetPrinterDataEx r2;
8361
8362         r2.in.handle            = r->in.handle;
8363         r2.in.key_name          = "PrinterDriverData";
8364         r2.in.value_name        = r->in.value_name;
8365         r2.in.type              = r->in.type;
8366         r2.in.data              = r->in.data;
8367         r2.in.offered           = r->in.offered;
8368
8369         return _spoolss_SetPrinterDataEx(p, &r2);
8370 }
8371
8372 /****************************************************************
8373  _spoolss_ResetPrinter
8374 ****************************************************************/
8375
8376 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8377                              struct spoolss_ResetPrinter *r)
8378 {
8379         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8380         int             snum;
8381
8382         DEBUG(5,("_spoolss_ResetPrinter\n"));
8383
8384         /*
8385          * All we do is to check to see if the handle and queue is valid.
8386          * This call really doesn't mean anything to us because we only
8387          * support RAW printing.   --jerry
8388          */
8389
8390         if (!Printer) {
8391                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8392                         OUR_HANDLE(r->in.handle)));
8393                 return WERR_BADFID;
8394         }
8395
8396         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8397                 return WERR_BADFID;
8398
8399
8400         /* blindly return success */
8401         return WERR_OK;
8402 }
8403
8404 /****************************************************************
8405  _spoolss_DeletePrinterData
8406 ****************************************************************/
8407
8408 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8409                                   struct spoolss_DeletePrinterData *r)
8410 {
8411         struct spoolss_DeletePrinterDataEx r2;
8412
8413         r2.in.handle            = r->in.handle;
8414         r2.in.key_name          = "PrinterDriverData";
8415         r2.in.value_name        = r->in.value_name;
8416
8417         return _spoolss_DeletePrinterDataEx(p, &r2);
8418 }
8419
8420 /****************************************************************
8421  _spoolss_AddForm
8422 ****************************************************************/
8423
8424 WERROR _spoolss_AddForm(struct pipes_struct *p,
8425                         struct spoolss_AddForm *r)
8426 {
8427         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8428         int snum = -1;
8429         WERROR status = WERR_OK;
8430
8431         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8432
8433         DEBUG(5,("_spoolss_AddForm\n"));
8434
8435         if (!Printer) {
8436                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8437                         OUR_HANDLE(r->in.handle)));
8438                 return WERR_BADFID;
8439         }
8440
8441         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8442            and not a printer admin, then fail */
8443
8444         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8445             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8446             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8447                                           p->session_info->info3->base.domain.string,
8448                                           NULL,
8449                                           p->session_info->security_token,
8450                                           lp_printer_admin(snum))) {
8451                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8452                 return WERR_ACCESS_DENIED;
8453         }
8454
8455         switch (form->flags) {
8456         case SPOOLSS_FORM_USER:
8457         case SPOOLSS_FORM_BUILTIN:
8458         case SPOOLSS_FORM_PRINTER:
8459                 break;
8460         default:
8461                 return WERR_INVALID_PARAM;
8462         }
8463
8464         status = winreg_printer_addform1(p->mem_ctx,
8465                                          get_session_info_system(),
8466                                          p->msg_ctx,
8467                                          form);
8468         if (!W_ERROR_IS_OK(status)) {
8469                 return status;
8470         }
8471
8472         /*
8473          * ChangeID must always be set if this is a printer
8474          */
8475         if (Printer->printer_type == SPLHND_PRINTER) {
8476                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8477                         return WERR_BADFID;
8478                 }
8479
8480                 status = winreg_printer_update_changeid(p->mem_ctx,
8481                                                         get_session_info_system(),
8482                                                         p->msg_ctx,
8483                                                         lp_const_servicename(snum));
8484                 if (!W_ERROR_IS_OK(status)) {
8485                         return status;
8486                 }
8487         }
8488
8489         return status;
8490 }
8491
8492 /****************************************************************
8493  _spoolss_DeleteForm
8494 ****************************************************************/
8495
8496 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8497                            struct spoolss_DeleteForm *r)
8498 {
8499         const char *form_name = r->in.form_name;
8500         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8501         int snum = -1;
8502         WERROR status = WERR_OK;
8503
8504         DEBUG(5,("_spoolss_DeleteForm\n"));
8505
8506         if (!Printer) {
8507                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8508                         OUR_HANDLE(r->in.handle)));
8509                 return WERR_BADFID;
8510         }
8511
8512         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8513             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8514             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8515                                           p->session_info->info3->base.domain.string,
8516                                           NULL,
8517                                           p->session_info->security_token,
8518                                           lp_printer_admin(snum))) {
8519                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8520                 return WERR_ACCESS_DENIED;
8521         }
8522
8523         status = winreg_printer_deleteform1(p->mem_ctx,
8524                                             get_session_info_system(),
8525                                             p->msg_ctx,
8526                                             form_name);
8527         if (!W_ERROR_IS_OK(status)) {
8528                 return status;
8529         }
8530
8531         /*
8532          * ChangeID must always be set if this is a printer
8533          */
8534         if (Printer->printer_type == SPLHND_PRINTER) {
8535                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8536                         return WERR_BADFID;
8537                 }
8538
8539                 status = winreg_printer_update_changeid(p->mem_ctx,
8540                                                         get_session_info_system(),
8541                                                         p->msg_ctx,
8542                                                         lp_const_servicename(snum));
8543                 if (!W_ERROR_IS_OK(status)) {
8544                         return status;
8545                 }
8546         }
8547
8548         return status;
8549 }
8550
8551 /****************************************************************
8552  _spoolss_SetForm
8553 ****************************************************************/
8554
8555 WERROR _spoolss_SetForm(struct pipes_struct *p,
8556                         struct spoolss_SetForm *r)
8557 {
8558         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8559         const char *form_name = r->in.form_name;
8560         int snum = -1;
8561         WERROR status = WERR_OK;
8562
8563         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8564
8565         DEBUG(5,("_spoolss_SetForm\n"));
8566
8567         if (!Printer) {
8568                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8569                         OUR_HANDLE(r->in.handle)));
8570                 return WERR_BADFID;
8571         }
8572
8573         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8574            and not a printer admin, then fail */
8575
8576         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8577              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8578              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8579                                           p->session_info->info3->base.domain.string,
8580                                           NULL,
8581                                           p->session_info->security_token,
8582                                           lp_printer_admin(snum))) {
8583                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8584                 return WERR_ACCESS_DENIED;
8585         }
8586
8587         status = winreg_printer_setform1(p->mem_ctx,
8588                                          get_session_info_system(),
8589                                          p->msg_ctx,
8590                                          form_name,
8591                                          form);
8592         if (!W_ERROR_IS_OK(status)) {
8593                 return status;
8594         }
8595
8596         /*
8597          * ChangeID must always be set if this is a printer
8598          */
8599         if (Printer->printer_type == SPLHND_PRINTER) {
8600                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8601                         return WERR_BADFID;
8602                 }
8603
8604                 status = winreg_printer_update_changeid(p->mem_ctx,
8605                                                         get_session_info_system(),
8606                                                         p->msg_ctx,
8607                                                         lp_const_servicename(snum));
8608                 if (!W_ERROR_IS_OK(status)) {
8609                         return status;
8610                 }
8611         }
8612
8613         return status;
8614 }
8615
8616 /****************************************************************************
8617  fill_print_processor1
8618 ****************************************************************************/
8619
8620 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8621                                     struct spoolss_PrintProcessorInfo1 *r,
8622                                     const char *print_processor_name)
8623 {
8624         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8625         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8626
8627         return WERR_OK;
8628 }
8629
8630 /****************************************************************************
8631  enumprintprocessors level 1.
8632 ****************************************************************************/
8633
8634 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8635                                           union spoolss_PrintProcessorInfo **info_p,
8636                                           uint32_t *count)
8637 {
8638         union spoolss_PrintProcessorInfo *info;
8639         WERROR result;
8640
8641         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8642         W_ERROR_HAVE_NO_MEMORY(info);
8643
8644         *count = 1;
8645
8646         result = fill_print_processor1(info, &info[0].info1, "winprint");
8647         if (!W_ERROR_IS_OK(result)) {
8648                 goto out;
8649         }
8650
8651  out:
8652         if (!W_ERROR_IS_OK(result)) {
8653                 TALLOC_FREE(info);
8654                 *count = 0;
8655                 return result;
8656         }
8657
8658         *info_p = info;
8659
8660         return WERR_OK;
8661 }
8662
8663 /****************************************************************
8664  _spoolss_EnumPrintProcessors
8665 ****************************************************************/
8666
8667 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8668                                     struct spoolss_EnumPrintProcessors *r)
8669 {
8670         WERROR result;
8671
8672         /* that's an [in out] buffer */
8673
8674         if (!r->in.buffer && (r->in.offered != 0)) {
8675                 return WERR_INVALID_PARAM;
8676         }
8677
8678         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8679
8680         /*
8681          * Enumerate the print processors ...
8682          *
8683          * Just reply with "winprint", to keep NT happy
8684          * and I can use my nice printer checker.
8685          */
8686
8687         *r->out.count = 0;
8688         *r->out.needed = 0;
8689         *r->out.info = NULL;
8690
8691         if (!get_short_archi(r->in.environment)) {
8692                 return WERR_INVALID_ENVIRONMENT;
8693         }
8694
8695         switch (r->in.level) {
8696         case 1:
8697                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8698                                                      r->out.count);
8699                 break;
8700         default:
8701                 return WERR_UNKNOWN_LEVEL;
8702         }
8703
8704         if (!W_ERROR_IS_OK(result)) {
8705                 return result;
8706         }
8707
8708         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8709                                                      spoolss_EnumPrintProcessors,
8710                                                      *r->out.info, r->in.level,
8711                                                      *r->out.count);
8712         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8713         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8714
8715         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8716 }
8717
8718 /****************************************************************************
8719  fill_printprocdatatype1
8720 ****************************************************************************/
8721
8722 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8723                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8724                                       const char *name_array)
8725 {
8726         r->name_array = talloc_strdup(mem_ctx, name_array);
8727         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8728
8729         return WERR_OK;
8730 }
8731
8732 /****************************************************************************
8733  enumprintprocdatatypes level 1.
8734 ****************************************************************************/
8735
8736 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8737                                              union spoolss_PrintProcDataTypesInfo **info_p,
8738                                              uint32_t *count)
8739 {
8740         WERROR result;
8741         union spoolss_PrintProcDataTypesInfo *info;
8742
8743         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8744         W_ERROR_HAVE_NO_MEMORY(info);
8745
8746         *count = 1;
8747
8748         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8749         if (!W_ERROR_IS_OK(result)) {
8750                 goto out;
8751         }
8752
8753  out:
8754         if (!W_ERROR_IS_OK(result)) {
8755                 TALLOC_FREE(info);
8756                 *count = 0;
8757                 return result;
8758         }
8759
8760         *info_p = info;
8761
8762         return WERR_OK;
8763 }
8764
8765 /****************************************************************
8766  _spoolss_EnumPrintProcDataTypes
8767 ****************************************************************/
8768
8769 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8770                                        struct spoolss_EnumPrintProcDataTypes *r)
8771 {
8772         WERROR result;
8773
8774         /* that's an [in out] buffer */
8775
8776         if (!r->in.buffer && (r->in.offered != 0)) {
8777                 return WERR_INVALID_PARAM;
8778         }
8779
8780         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8781
8782         *r->out.count = 0;
8783         *r->out.needed = 0;
8784         *r->out.info = NULL;
8785
8786         if (r->in.print_processor_name == NULL ||
8787             !strequal(r->in.print_processor_name, "winprint")) {
8788                 return WERR_UNKNOWN_PRINTPROCESSOR;
8789         }
8790
8791         switch (r->in.level) {
8792         case 1:
8793                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8794                                                         r->out.count);
8795                 break;
8796         default:
8797                 return WERR_UNKNOWN_LEVEL;
8798         }
8799
8800         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8801                                                      spoolss_EnumPrintProcDataTypes,
8802                                                      *r->out.info, r->in.level,
8803                                                      *r->out.count);
8804         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8805         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8806
8807         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8808 }
8809
8810 /****************************************************************************
8811  fill_monitor_1
8812 ****************************************************************************/
8813
8814 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8815                              struct spoolss_MonitorInfo1 *r,
8816                              const char *monitor_name)
8817 {
8818         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8819         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8820
8821         return WERR_OK;
8822 }
8823
8824 /****************************************************************************
8825  fill_monitor_2
8826 ****************************************************************************/
8827
8828 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8829                              struct spoolss_MonitorInfo2 *r,
8830                              const char *monitor_name,
8831                              const char *environment,
8832                              const char *dll_name)
8833 {
8834         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8835         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8836         r->environment                  = talloc_strdup(mem_ctx, environment);
8837         W_ERROR_HAVE_NO_MEMORY(r->environment);
8838         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8839         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8840
8841         return WERR_OK;
8842 }
8843
8844 /****************************************************************************
8845  enumprintmonitors level 1.
8846 ****************************************************************************/
8847
8848 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8849                                         union spoolss_MonitorInfo **info_p,
8850                                         uint32_t *count)
8851 {
8852         union spoolss_MonitorInfo *info;
8853         WERROR result = WERR_OK;
8854
8855         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8856         W_ERROR_HAVE_NO_MEMORY(info);
8857
8858         *count = 2;
8859
8860         result = fill_monitor_1(info, &info[0].info1,
8861                                 SPL_LOCAL_PORT);
8862         if (!W_ERROR_IS_OK(result)) {
8863                 goto out;
8864         }
8865
8866         result = fill_monitor_1(info, &info[1].info1,
8867                                 SPL_TCPIP_PORT);
8868         if (!W_ERROR_IS_OK(result)) {
8869                 goto out;
8870         }
8871
8872 out:
8873         if (!W_ERROR_IS_OK(result)) {
8874                 TALLOC_FREE(info);
8875                 *count = 0;
8876                 return result;
8877         }
8878
8879         *info_p = info;
8880
8881         return WERR_OK;
8882 }
8883
8884 /****************************************************************************
8885  enumprintmonitors level 2.
8886 ****************************************************************************/
8887
8888 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8889                                         union spoolss_MonitorInfo **info_p,
8890                                         uint32_t *count)
8891 {
8892         union spoolss_MonitorInfo *info;
8893         WERROR result = WERR_OK;
8894
8895         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8896         W_ERROR_HAVE_NO_MEMORY(info);
8897
8898         *count = 2;
8899
8900         result = fill_monitor_2(info, &info[0].info2,
8901                                 SPL_LOCAL_PORT,
8902                                 "Windows NT X86", /* FIXME */
8903                                 "localmon.dll");
8904         if (!W_ERROR_IS_OK(result)) {
8905                 goto out;
8906         }
8907
8908         result = fill_monitor_2(info, &info[1].info2,
8909                                 SPL_TCPIP_PORT,
8910                                 "Windows NT X86", /* FIXME */
8911                                 "tcpmon.dll");
8912         if (!W_ERROR_IS_OK(result)) {
8913                 goto out;
8914         }
8915
8916 out:
8917         if (!W_ERROR_IS_OK(result)) {
8918                 TALLOC_FREE(info);
8919                 *count = 0;
8920                 return result;
8921         }
8922
8923         *info_p = info;
8924
8925         return WERR_OK;
8926 }
8927
8928 /****************************************************************
8929  _spoolss_EnumMonitors
8930 ****************************************************************/
8931
8932 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8933                              struct spoolss_EnumMonitors *r)
8934 {
8935         WERROR result;
8936
8937         /* that's an [in out] buffer */
8938
8939         if (!r->in.buffer && (r->in.offered != 0)) {
8940                 return WERR_INVALID_PARAM;
8941         }
8942
8943         DEBUG(5,("_spoolss_EnumMonitors\n"));
8944
8945         /*
8946          * Enumerate the print monitors ...
8947          *
8948          * Just reply with "Local Port", to keep NT happy
8949          * and I can use my nice printer checker.
8950          */
8951
8952         *r->out.count = 0;
8953         *r->out.needed = 0;
8954         *r->out.info = NULL;
8955
8956         switch (r->in.level) {
8957         case 1:
8958                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8959                                                    r->out.count);
8960                 break;
8961         case 2:
8962                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8963                                                    r->out.count);
8964                 break;
8965         default:
8966                 return WERR_UNKNOWN_LEVEL;
8967         }
8968
8969         if (!W_ERROR_IS_OK(result)) {
8970                 return result;
8971         }
8972
8973         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8974                                                      spoolss_EnumMonitors,
8975                                                      *r->out.info, r->in.level,
8976                                                      *r->out.count);
8977         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8978         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8979
8980         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8981 }
8982
8983 /****************************************************************************
8984 ****************************************************************************/
8985
8986 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8987                              const print_queue_struct *queue,
8988                              int count, int snum,
8989                              struct spoolss_PrinterInfo2 *pinfo2,
8990                              uint32_t jobid,
8991                              struct spoolss_JobInfo1 *r)
8992 {
8993         int i = 0;
8994         bool found = false;
8995
8996         for (i=0; i<count; i++) {
8997                 if (queue[i].job == (int)jobid) {
8998                         found = true;
8999                         break;
9000                 }
9001         }
9002
9003         if (found == false) {
9004                 /* NT treats not found as bad param... yet another bad choice */
9005                 return WERR_INVALID_PARAM;
9006         }
9007
9008         return fill_job_info1(mem_ctx,
9009                               r,
9010                               &queue[i],
9011                               i,
9012                               snum,
9013                               pinfo2);
9014 }
9015
9016 /****************************************************************************
9017 ****************************************************************************/
9018
9019 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9020                              const print_queue_struct *queue,
9021                              int count, int snum,
9022                              struct spoolss_PrinterInfo2 *pinfo2,
9023                              uint32_t jobid,
9024                              struct spoolss_JobInfo2 *r)
9025 {
9026         int i = 0;
9027         bool found = false;
9028         struct spoolss_DeviceMode *devmode;
9029         WERROR result;
9030
9031         for (i=0; i<count; i++) {
9032                 if (queue[i].job == (int)jobid) {
9033                         found = true;
9034                         break;
9035                 }
9036         }
9037
9038         if (found == false) {
9039                 /* NT treats not found as bad param... yet another bad
9040                    choice */
9041                 return WERR_INVALID_PARAM;
9042         }
9043
9044         /*
9045          * if the print job does not have a DEVMODE associated with it,
9046          * just use the one for the printer. A NULL devicemode is not
9047          *  a failure condition
9048          */
9049
9050         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9051         if (!devmode) {
9052                 result = spoolss_create_default_devmode(mem_ctx,
9053                                                 pinfo2->printername,
9054                                                 &devmode);
9055                 if (!W_ERROR_IS_OK(result)) {
9056                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9057                         return result;
9058                 }
9059         }
9060
9061         return fill_job_info2(mem_ctx,
9062                               r,
9063                               &queue[i],
9064                               i,
9065                               snum,
9066                               pinfo2,
9067                               devmode);
9068 }
9069
9070 /****************************************************************
9071  _spoolss_GetJob
9072 ****************************************************************/
9073
9074 WERROR _spoolss_GetJob(struct pipes_struct *p,
9075                        struct spoolss_GetJob *r)
9076 {
9077         WERROR result = WERR_OK;
9078         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9079         int snum;
9080         int count;
9081         print_queue_struct      *queue = NULL;
9082         print_status_struct prt_status;
9083
9084         /* that's an [in out] buffer */
9085
9086         if (!r->in.buffer && (r->in.offered != 0)) {
9087                 return WERR_INVALID_PARAM;
9088         }
9089
9090         DEBUG(5,("_spoolss_GetJob\n"));
9091
9092         *r->out.needed = 0;
9093
9094         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9095                 return WERR_BADFID;
9096         }
9097
9098         result = winreg_get_printer(p->mem_ctx,
9099                                     get_session_info_system(),
9100                                     p->msg_ctx,
9101                                     lp_const_servicename(snum),
9102                                     &pinfo2);
9103         if (!W_ERROR_IS_OK(result)) {
9104                 return result;
9105         }
9106
9107         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9108
9109         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9110                      count, prt_status.status, prt_status.message));
9111
9112         switch (r->in.level) {
9113         case 1:
9114                 result = getjob_level_1(p->mem_ctx,
9115                                         queue, count, snum, pinfo2,
9116                                         r->in.job_id, &r->out.info->info1);
9117                 break;
9118         case 2:
9119                 result = getjob_level_2(p->mem_ctx,
9120                                         queue, count, snum, pinfo2,
9121                                         r->in.job_id, &r->out.info->info2);
9122                 break;
9123         default:
9124                 result = WERR_UNKNOWN_LEVEL;
9125                 break;
9126         }
9127
9128         SAFE_FREE(queue);
9129         TALLOC_FREE(pinfo2);
9130
9131         if (!W_ERROR_IS_OK(result)) {
9132                 TALLOC_FREE(r->out.info);
9133                 return result;
9134         }
9135
9136         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9137                                                                                    r->in.level);
9138         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9139
9140         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9141 }
9142
9143 /****************************************************************
9144  _spoolss_GetPrinterDataEx
9145 ****************************************************************/
9146
9147 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9148                                  struct spoolss_GetPrinterDataEx *r)
9149 {
9150
9151         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9152         const char *printer;
9153         int                     snum = 0;
9154         WERROR result = WERR_OK;
9155         DATA_BLOB blob;
9156         enum winreg_Type val_type;
9157         uint8_t *val_data;
9158         uint32_t val_size;
9159
9160
9161         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9162
9163         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9164                 r->in.key_name, r->in.value_name));
9165
9166         /* in case of problem, return some default values */
9167
9168         *r->out.needed  = 0;
9169         *r->out.type    = REG_NONE;
9170
9171         if (!Printer) {
9172                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9173                         OUR_HANDLE(r->in.handle)));
9174                 result = WERR_BADFID;
9175                 goto done;
9176         }
9177
9178         /* Is the handle to a printer or to the server? */
9179
9180         if (Printer->printer_type == SPLHND_SERVER) {
9181
9182                 union spoolss_PrinterData data;
9183
9184                 result = getprinterdata_printer_server(p->mem_ctx,
9185                                                        r->in.value_name,
9186                                                        r->out.type,
9187                                                        &data);
9188                 if (!W_ERROR_IS_OK(result)) {
9189                         return result;
9190                 }
9191
9192                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9193                                                   *r->out.type, &data);
9194                 if (!W_ERROR_IS_OK(result)) {
9195                         return result;
9196                 }
9197
9198                 *r->out.needed = blob.length;
9199
9200                 if (r->in.offered >= *r->out.needed) {
9201                         memcpy(r->out.data, blob.data, blob.length);
9202                 }
9203
9204                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9205         }
9206
9207         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9208                 return WERR_BADFID;
9209         }
9210         printer = lp_const_servicename(snum);
9211
9212         /* check to see if the keyname is valid */
9213         if (!strlen(r->in.key_name)) {
9214                 return WERR_INVALID_PARAM;
9215         }
9216
9217         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9218         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9219             strequal(r->in.value_name, "ChangeId")) {
9220                 *r->out.type = REG_DWORD;
9221                 *r->out.needed = 4;
9222                 if (r->in.offered >= *r->out.needed) {
9223                         uint32_t changeid = 0;
9224
9225                         result = winreg_printer_get_changeid(p->mem_ctx,
9226                                                              get_session_info_system(),
9227                                                              p->msg_ctx,
9228                                                              printer,
9229                                                              &changeid);
9230                         if (!W_ERROR_IS_OK(result)) {
9231                                 return result;
9232                         }
9233
9234                         SIVAL(r->out.data, 0, changeid);
9235                         result = WERR_OK;
9236                 }
9237                 goto done;
9238         }
9239
9240         result = winreg_get_printer_dataex(p->mem_ctx,
9241                                            get_session_info_system(),
9242                                            p->msg_ctx,
9243                                            printer,
9244                                            r->in.key_name,
9245                                            r->in.value_name,
9246                                            &val_type,
9247                                            &val_data,
9248                                            &val_size);
9249         if (!W_ERROR_IS_OK(result)) {
9250                 return result;
9251         }
9252
9253         *r->out.needed = val_size;
9254         *r->out.type = val_type;
9255
9256         if (r->in.offered >= *r->out.needed) {
9257                 memcpy(r->out.data, val_data, val_size);
9258         }
9259
9260  done:
9261         /* retain type when returning WERR_MORE_DATA */
9262         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9263
9264         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9265 }
9266
9267 /****************************************************************
9268  _spoolss_SetPrinterDataEx
9269 ****************************************************************/
9270
9271 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9272                                  struct spoolss_SetPrinterDataEx *r)
9273 {
9274         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9275         int                     snum = 0;
9276         WERROR                  result = WERR_OK;
9277         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9278         char                    *oid_string;
9279
9280         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9281
9282         /* From MSDN documentation of SetPrinterDataEx: pass request to
9283            SetPrinterData if key is "PrinterDriverData" */
9284
9285         if (!Printer) {
9286                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9287                         OUR_HANDLE(r->in.handle)));
9288                 return WERR_BADFID;
9289         }
9290
9291         if (Printer->printer_type == SPLHND_SERVER) {
9292                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9293                         "Not implemented for server handles yet\n"));
9294                 return WERR_INVALID_PARAM;
9295         }
9296
9297         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9298                 return WERR_BADFID;
9299         }
9300
9301         /*
9302          * Access check : NT returns "access denied" if you make a
9303          * SetPrinterData call without the necessary privildge.
9304          * we were originally returning OK if nothing changed
9305          * which made Win2k issue **a lot** of SetPrinterData
9306          * when connecting to a printer  --jerry
9307          */
9308
9309         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9310                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9311                         "change denied by handle access permissions\n"));
9312                 return WERR_ACCESS_DENIED;
9313         }
9314
9315         result = winreg_get_printer(Printer,
9316                                     get_session_info_system(),
9317                                     p->msg_ctx,
9318                                     lp_servicename(snum),
9319                                     &pinfo2);
9320         if (!W_ERROR_IS_OK(result)) {
9321                 return result;
9322         }
9323
9324         /* check for OID in valuename */
9325
9326         oid_string = strchr(r->in.value_name, ',');
9327         if (oid_string) {
9328                 *oid_string = '\0';
9329                 oid_string++;
9330         }
9331
9332         /* save the registry data */
9333
9334         result = winreg_set_printer_dataex(p->mem_ctx,
9335                                            get_session_info_system(),
9336                                            p->msg_ctx,
9337                                            pinfo2->sharename,
9338                                            r->in.key_name,
9339                                            r->in.value_name,
9340                                            r->in.type,
9341                                            r->in.data,
9342                                            r->in.offered);
9343
9344         if (W_ERROR_IS_OK(result)) {
9345                 /* save the OID if one was specified */
9346                 if (oid_string) {
9347                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9348                                 r->in.key_name, SPOOL_OID_KEY);
9349                         if (!str) {
9350                                 result = WERR_NOMEM;
9351                                 goto done;
9352                         }
9353
9354                         /*
9355                          * I'm not checking the status here on purpose.  Don't know
9356                          * if this is right, but I'm returning the status from the
9357                          * previous set_printer_dataex() call.  I have no idea if
9358                          * this is right.    --jerry
9359                          */
9360                         winreg_set_printer_dataex(p->mem_ctx,
9361                                                   get_session_info_system(),
9362                                                   p->msg_ctx,
9363                                                   pinfo2->sharename,
9364                                                   str,
9365                                                   r->in.value_name,
9366                                                   REG_SZ,
9367                                                   (uint8_t *) oid_string,
9368                                                   strlen(oid_string) + 1);
9369                 }
9370
9371                 result = winreg_printer_update_changeid(p->mem_ctx,
9372                                                         get_session_info_system(),
9373                                                         p->msg_ctx,
9374                                                         lp_const_servicename(snum));
9375
9376         }
9377
9378 done:
9379         talloc_free(pinfo2);
9380         return result;
9381 }
9382
9383 /****************************************************************
9384  _spoolss_DeletePrinterDataEx
9385 ****************************************************************/
9386
9387 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9388                                     struct spoolss_DeletePrinterDataEx *r)
9389 {
9390         const char *printer;
9391         int             snum=0;
9392         WERROR          status = WERR_OK;
9393         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9394
9395         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9396
9397         if (!Printer) {
9398                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9399                         "Invalid handle (%s:%u:%u).\n",
9400                         OUR_HANDLE(r->in.handle)));
9401                 return WERR_BADFID;
9402         }
9403
9404         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9405                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9406                         "printer properties change denied by handle\n"));
9407                 return WERR_ACCESS_DENIED;
9408         }
9409
9410         if (!r->in.value_name || !r->in.key_name) {
9411                 return WERR_NOMEM;
9412         }
9413
9414         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9415                 return WERR_BADFID;
9416         }
9417         printer = lp_const_servicename(snum);
9418
9419         status = winreg_delete_printer_dataex(p->mem_ctx,
9420                                               get_session_info_system(),
9421                                               p->msg_ctx,
9422                                               printer,
9423                                               r->in.key_name,
9424                                               r->in.value_name);
9425         if (W_ERROR_IS_OK(status)) {
9426                 status = winreg_printer_update_changeid(p->mem_ctx,
9427                                                         get_session_info_system(),
9428                                                         p->msg_ctx,
9429                                                         printer);
9430         }
9431
9432         return status;
9433 }
9434
9435 /****************************************************************
9436  _spoolss_EnumPrinterKey
9437 ****************************************************************/
9438
9439 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9440                                struct spoolss_EnumPrinterKey *r)
9441 {
9442         uint32_t        num_keys;
9443         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9444         int             snum = 0;
9445         WERROR          result = WERR_BADFILE;
9446         const char **array = NULL;
9447         DATA_BLOB blob;
9448
9449         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9450
9451         if (!Printer) {
9452                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9453                         OUR_HANDLE(r->in.handle)));
9454                 return WERR_BADFID;
9455         }
9456
9457         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9458                 return WERR_BADFID;
9459         }
9460
9461         result = winreg_enum_printer_key(p->mem_ctx,
9462                                          get_session_info_system(),
9463                                          p->msg_ctx,
9464                                          lp_const_servicename(snum),
9465                                          r->in.key_name,
9466                                          &num_keys,
9467                                          &array);
9468         if (!W_ERROR_IS_OK(result)) {
9469                 goto done;
9470         }
9471
9472         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9473                 result = WERR_NOMEM;
9474                 goto done;
9475         }
9476
9477         *r->out._ndr_size = r->in.offered / 2;
9478         *r->out.needed = blob.length;
9479
9480         if (r->in.offered < *r->out.needed) {
9481                 result = WERR_MORE_DATA;
9482         } else {
9483                 result = WERR_OK;
9484                 r->out.key_buffer->string_array = array;
9485         }
9486
9487  done:
9488         if (!W_ERROR_IS_OK(result)) {
9489                 TALLOC_FREE(array);
9490                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9491                         *r->out.needed = 0;
9492                 }
9493         }
9494
9495         return result;
9496 }
9497
9498 /****************************************************************
9499  _spoolss_DeletePrinterKey
9500 ****************************************************************/
9501
9502 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9503                                  struct spoolss_DeletePrinterKey *r)
9504 {
9505         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9506         int                     snum=0;
9507         WERROR                  status;
9508         const char *printer;
9509
9510         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9511
9512         if (!Printer) {
9513                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9514                         OUR_HANDLE(r->in.handle)));
9515                 return WERR_BADFID;
9516         }
9517
9518         /* if keyname == NULL, return error */
9519         if ( !r->in.key_name )
9520                 return WERR_INVALID_PARAM;
9521
9522         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9523                 return WERR_BADFID;
9524         }
9525
9526         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9527                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9528                         "printer properties change denied by handle\n"));
9529                 return WERR_ACCESS_DENIED;
9530         }
9531
9532         printer = lp_const_servicename(snum);
9533
9534         /* delete the key and all subkeys */
9535         status = winreg_delete_printer_key(p->mem_ctx,
9536                                            get_session_info_system(),
9537                                            p->msg_ctx,
9538                                            printer,
9539                                            r->in.key_name);
9540         if (W_ERROR_IS_OK(status)) {
9541                 status = winreg_printer_update_changeid(p->mem_ctx,
9542                                                         get_session_info_system(),
9543                                                         p->msg_ctx,
9544                                                         printer);
9545         }
9546
9547         return status;
9548 }
9549
9550 /****************************************************************
9551  _spoolss_EnumPrinterDataEx
9552 ****************************************************************/
9553
9554 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9555                                   struct spoolss_EnumPrinterDataEx *r)
9556 {
9557         uint32_t        count = 0;
9558         struct spoolss_PrinterEnumValues *info = NULL;
9559         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9560         int             snum;
9561         WERROR          result;
9562
9563         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9564
9565         *r->out.count = 0;
9566         *r->out.needed = 0;
9567         *r->out.info = NULL;
9568
9569         if (!Printer) {
9570                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9571                         OUR_HANDLE(r->in.handle)));
9572                 return WERR_BADFID;
9573         }
9574
9575         /*
9576          * first check for a keyname of NULL or "".  Win2k seems to send
9577          * this a lot and we should send back WERR_INVALID_PARAM
9578          * no need to spend time looking up the printer in this case.
9579          * --jerry
9580          */
9581
9582         if (!strlen(r->in.key_name)) {
9583                 result = WERR_INVALID_PARAM;
9584                 goto done;
9585         }
9586
9587         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9588                 return WERR_BADFID;
9589         }
9590
9591         /* now look for a match on the key name */
9592         result = winreg_enum_printer_dataex(p->mem_ctx,
9593                                             get_session_info_system(),
9594                                             p->msg_ctx,
9595                                             lp_const_servicename(snum),
9596                                             r->in.key_name,
9597                                             &count,
9598                                             &info);
9599         if (!W_ERROR_IS_OK(result)) {
9600                 goto done;
9601         }
9602
9603 #if 0 /* FIXME - gd */
9604         /* housekeeping information in the reply */
9605
9606         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9607          * the hand marshalled container size is a multiple
9608          * of 4 bytes for RPC alignment.
9609          */
9610
9611         if (needed % 4) {
9612                 needed += 4-(needed % 4);
9613         }
9614 #endif
9615         *r->out.count   = count;
9616         *r->out.info    = info;
9617
9618  done:
9619         if (!W_ERROR_IS_OK(result)) {
9620                 return result;
9621         }
9622
9623         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9624                                                spoolss_EnumPrinterDataEx,
9625                                                *r->out.info,
9626                                                *r->out.count);
9627         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9628         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9629
9630         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9631 }
9632
9633 /****************************************************************************
9634 ****************************************************************************/
9635
9636 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9637                                                  const char *servername,
9638                                                  const char *environment,
9639                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9640 {
9641         WERROR werr;
9642         char *path = NULL;
9643
9644         werr = compose_spoolss_server_path(mem_ctx,
9645                                            servername,
9646                                            environment,
9647                                            SPOOLSS_PRTPROCS_PATH,
9648                                            &path);
9649         if (!W_ERROR_IS_OK(werr)) {
9650                 return werr;
9651         }
9652
9653         DEBUG(4,("print processor directory: [%s]\n", path));
9654
9655         r->directory_name = path;
9656
9657         return WERR_OK;
9658 }
9659
9660 /****************************************************************
9661  _spoolss_GetPrintProcessorDirectory
9662 ****************************************************************/
9663
9664 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9665                                            struct spoolss_GetPrintProcessorDirectory *r)
9666 {
9667         WERROR result;
9668         char *prnproc_share = NULL;
9669         bool prnproc_share_exists = false;
9670         int snum;
9671
9672         /* that's an [in out] buffer */
9673
9674         if (!r->in.buffer && (r->in.offered != 0)) {
9675                 return WERR_INVALID_PARAM;
9676         }
9677
9678         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9679                 r->in.level));
9680
9681         *r->out.needed = 0;
9682
9683         /* r->in.level is ignored */
9684
9685         /* We always should reply with a local print processor directory so that
9686          * users are not forced to have a [prnproc$] share on the Samba spoolss
9687          * server, if users decide to do so, lets announce it though - Guenther */
9688
9689         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9690         if (!prnproc_share) {
9691                 return WERR_NOMEM;
9692         }
9693         if (snum != -1) {
9694                 prnproc_share_exists = true;
9695         }
9696
9697         result = getprintprocessordirectory_level_1(p->mem_ctx,
9698                                                     prnproc_share_exists ? r->in.server : NULL,
9699                                                     r->in.environment,
9700                                                     &r->out.info->info1);
9701         if (!W_ERROR_IS_OK(result)) {
9702                 TALLOC_FREE(r->out.info);
9703                 return result;
9704         }
9705
9706         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9707                                                                                    r->out.info, r->in.level);
9708         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9709
9710         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9711 }
9712
9713 /*******************************************************************
9714  ********************************************************************/
9715
9716 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9717                                const char *dllname)
9718 {
9719         enum ndr_err_code ndr_err;
9720         struct spoolss_MonitorUi ui;
9721
9722         ui.dll_name = dllname;
9723
9724         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9725                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9726         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9727                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9728         }
9729         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9730 }
9731
9732 /*******************************************************************
9733  Streams the monitor UI DLL name in UNICODE
9734 *******************************************************************/
9735
9736 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9737                                struct security_token *token, DATA_BLOB *in,
9738                                DATA_BLOB *out, uint32_t *needed)
9739 {
9740         const char *dllname = "tcpmonui.dll";
9741
9742         *needed = (strlen(dllname)+1) * 2;
9743
9744         if (out->length < *needed) {
9745                 return WERR_INSUFFICIENT_BUFFER;
9746         }
9747
9748         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9749                 return WERR_NOMEM;
9750         }
9751
9752         return WERR_OK;
9753 }
9754
9755 /*******************************************************************
9756  ********************************************************************/
9757
9758 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9759                              struct spoolss_PortData1 *port1,
9760                              const DATA_BLOB *buf)
9761 {
9762         enum ndr_err_code ndr_err;
9763         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9764                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9765         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9766                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9767         }
9768         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9769 }
9770
9771 /*******************************************************************
9772  ********************************************************************/
9773
9774 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9775                              struct spoolss_PortData2 *port2,
9776                              const DATA_BLOB *buf)
9777 {
9778         enum ndr_err_code ndr_err;
9779         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9780                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9781         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9782                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9783         }
9784         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9785 }
9786
9787 /*******************************************************************
9788  Create a new TCP/IP port
9789 *******************************************************************/
9790
9791 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9792                              struct security_token *token, DATA_BLOB *in,
9793                              DATA_BLOB *out, uint32_t *needed)
9794 {
9795         struct spoolss_PortData1 port1;
9796         struct spoolss_PortData2 port2;
9797         char *device_uri = NULL;
9798         uint32_t version;
9799
9800         const char *portname;
9801         const char *hostaddress;
9802         const char *queue;
9803         uint32_t port_number;
9804         uint32_t protocol;
9805
9806         /* peek for spoolss_PortData version */
9807
9808         if (!in || (in->length < (128 + 4))) {
9809                 return WERR_GENERAL_FAILURE;
9810         }
9811
9812         version = IVAL(in->data, 128);
9813
9814         switch (version) {
9815                 case 1:
9816                         ZERO_STRUCT(port1);
9817
9818                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9819                                 return WERR_NOMEM;
9820                         }
9821
9822                         portname        = port1.portname;
9823                         hostaddress     = port1.hostaddress;
9824                         queue           = port1.queue;
9825                         protocol        = port1.protocol;
9826                         port_number     = port1.port_number;
9827
9828                         break;
9829                 case 2:
9830                         ZERO_STRUCT(port2);
9831
9832                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9833                                 return WERR_NOMEM;
9834                         }
9835
9836                         portname        = port2.portname;
9837                         hostaddress     = port2.hostaddress;
9838                         queue           = port2.queue;
9839                         protocol        = port2.protocol;
9840                         port_number     = port2.port_number;
9841
9842                         break;
9843                 default:
9844                         DEBUG(1,("xcvtcp_addport: "
9845                                 "unknown version of port_data: %d\n", version));
9846                         return WERR_UNKNOWN_PORT;
9847         }
9848
9849         /* create the device URI and call the add_port_hook() */
9850
9851         switch (protocol) {
9852         case PROTOCOL_RAWTCP_TYPE:
9853                 device_uri = talloc_asprintf(mem_ctx,
9854                                 "socket://%s:%d/", hostaddress,
9855                                 port_number);
9856                 break;
9857
9858         case PROTOCOL_LPR_TYPE:
9859                 device_uri = talloc_asprintf(mem_ctx,
9860                         "lpr://%s/%s", hostaddress, queue );
9861                 break;
9862
9863         default:
9864                 return WERR_UNKNOWN_PORT;
9865         }
9866
9867         if (!device_uri) {
9868                 return WERR_NOMEM;
9869         }
9870
9871         return add_port_hook(mem_ctx, token, portname, device_uri);
9872 }
9873
9874 /*******************************************************************
9875 *******************************************************************/
9876
9877 struct xcv_api_table xcvtcp_cmds[] = {
9878         { "MonitorUI",  xcvtcp_monitorui },
9879         { "AddPort",    xcvtcp_addport},
9880         { NULL,         NULL }
9881 };
9882
9883 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9884                                      struct security_token *token, const char *command,
9885                                      DATA_BLOB *inbuf,
9886                                      DATA_BLOB *outbuf,
9887                                      uint32_t *needed )
9888 {
9889         int i;
9890
9891         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9892
9893         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9894                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9895                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9896         }
9897
9898         return WERR_BADFUNC;
9899 }
9900
9901 /*******************************************************************
9902 *******************************************************************/
9903 #if 0   /* don't support management using the "Local Port" monitor */
9904
9905 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9906                                  struct security_token *token, DATA_BLOB *in,
9907                                  DATA_BLOB *out, uint32_t *needed)
9908 {
9909         const char *dllname = "localui.dll";
9910
9911         *needed = (strlen(dllname)+1) * 2;
9912
9913         if (out->length < *needed) {
9914                 return WERR_INSUFFICIENT_BUFFER;
9915         }
9916
9917         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9918                 return WERR_NOMEM;
9919         }
9920
9921         return WERR_OK;
9922 }
9923
9924 /*******************************************************************
9925 *******************************************************************/
9926
9927 struct xcv_api_table xcvlocal_cmds[] = {
9928         { "MonitorUI",  xcvlocal_monitorui },
9929         { NULL,         NULL }
9930 };
9931 #else
9932 struct xcv_api_table xcvlocal_cmds[] = {
9933         { NULL,         NULL }
9934 };
9935 #endif
9936
9937
9938
9939 /*******************************************************************
9940 *******************************************************************/
9941
9942 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9943                                        struct security_token *token, const char *command,
9944                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9945                                        uint32_t *needed)
9946 {
9947         int i;
9948
9949         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9950
9951         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9952                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9953                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9954         }
9955         return WERR_BADFUNC;
9956 }
9957
9958 /****************************************************************
9959  _spoolss_XcvData
9960 ****************************************************************/
9961
9962 WERROR _spoolss_XcvData(struct pipes_struct *p,
9963                         struct spoolss_XcvData *r)
9964 {
9965         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9966         DATA_BLOB out_data = data_blob_null;
9967         WERROR werror;
9968
9969         if (!Printer) {
9970                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9971                         OUR_HANDLE(r->in.handle)));
9972                 return WERR_BADFID;
9973         }
9974
9975         /* Has to be a handle to the TCP/IP port monitor */
9976
9977         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9978                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9979                 return WERR_BADFID;
9980         }
9981
9982         /* requires administrative access to the server */
9983
9984         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9985                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9986                 return WERR_ACCESS_DENIED;
9987         }
9988
9989         /* Allocate the outgoing buffer */
9990
9991         if (r->in.out_data_size) {
9992                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9993                 if (out_data.data == NULL) {
9994                         return WERR_NOMEM;
9995                 }
9996         }
9997
9998         switch ( Printer->printer_type ) {
9999         case SPLHND_PORTMON_TCP:
10000                 werror = process_xcvtcp_command(p->mem_ctx,
10001                                                 p->session_info->security_token,
10002                                                 r->in.function_name,
10003                                                 &r->in.in_data, &out_data,
10004                                                 r->out.needed);
10005                 break;
10006         case SPLHND_PORTMON_LOCAL:
10007                 werror = process_xcvlocal_command(p->mem_ctx,
10008                                                   p->session_info->security_token,
10009                                                   r->in.function_name,
10010                                                   &r->in.in_data, &out_data,
10011                                                   r->out.needed);
10012                 break;
10013         default:
10014                 werror = WERR_INVALID_PRINT_MONITOR;
10015         }
10016
10017         if (!W_ERROR_IS_OK(werror)) {
10018                 return werror;
10019         }
10020
10021         *r->out.status_code = 0;
10022
10023         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10024                 memcpy(r->out.out_data, out_data.data,
10025                         MIN(r->in.out_data_size, out_data.length));
10026         }
10027
10028         return WERR_OK;
10029 }
10030
10031 /****************************************************************
10032  _spoolss_AddPrintProcessor
10033 ****************************************************************/
10034
10035 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10036                                   struct spoolss_AddPrintProcessor *r)
10037 {
10038         /* for now, just indicate success and ignore the add.  We'll
10039            automatically set the winprint processor for printer
10040            entries later.  Used to debug the LexMark Optra S 1855 PCL
10041            driver --jerry */
10042
10043         return WERR_OK;
10044 }
10045
10046 /****************************************************************
10047  _spoolss_AddPort
10048 ****************************************************************/
10049
10050 WERROR _spoolss_AddPort(struct pipes_struct *p,
10051                         struct spoolss_AddPort *r)
10052 {
10053         /* do what w2k3 does */
10054
10055         return WERR_NOT_SUPPORTED;
10056 }
10057
10058 /****************************************************************
10059  _spoolss_GetPrinterDriver
10060 ****************************************************************/
10061
10062 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10063                                  struct spoolss_GetPrinterDriver *r)
10064 {
10065         p->rng_fault_state = true;
10066         return WERR_NOT_SUPPORTED;
10067 }
10068
10069 /****************************************************************
10070  _spoolss_ReadPrinter
10071 ****************************************************************/
10072
10073 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10074                             struct spoolss_ReadPrinter *r)
10075 {
10076         p->rng_fault_state = true;
10077         return WERR_NOT_SUPPORTED;
10078 }
10079
10080 /****************************************************************
10081  _spoolss_WaitForPrinterChange
10082 ****************************************************************/
10083
10084 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10085                                      struct spoolss_WaitForPrinterChange *r)
10086 {
10087         p->rng_fault_state = true;
10088         return WERR_NOT_SUPPORTED;
10089 }
10090
10091 /****************************************************************
10092  _spoolss_ConfigurePort
10093 ****************************************************************/
10094
10095 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10096                               struct spoolss_ConfigurePort *r)
10097 {
10098         p->rng_fault_state = true;
10099         return WERR_NOT_SUPPORTED;
10100 }
10101
10102 /****************************************************************
10103  _spoolss_DeletePort
10104 ****************************************************************/
10105
10106 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10107                            struct spoolss_DeletePort *r)
10108 {
10109         p->rng_fault_state = true;
10110         return WERR_NOT_SUPPORTED;
10111 }
10112
10113 /****************************************************************
10114  _spoolss_CreatePrinterIC
10115 ****************************************************************/
10116
10117 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10118                                 struct spoolss_CreatePrinterIC *r)
10119 {
10120         p->rng_fault_state = true;
10121         return WERR_NOT_SUPPORTED;
10122 }
10123
10124 /****************************************************************
10125  _spoolss_PlayGDIScriptOnPrinterIC
10126 ****************************************************************/
10127
10128 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10129                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10130 {
10131         p->rng_fault_state = true;
10132         return WERR_NOT_SUPPORTED;
10133 }
10134
10135 /****************************************************************
10136  _spoolss_DeletePrinterIC
10137 ****************************************************************/
10138
10139 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10140                                 struct spoolss_DeletePrinterIC *r)
10141 {
10142         p->rng_fault_state = true;
10143         return WERR_NOT_SUPPORTED;
10144 }
10145
10146 /****************************************************************
10147  _spoolss_AddPrinterConnection
10148 ****************************************************************/
10149
10150 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10151                                      struct spoolss_AddPrinterConnection *r)
10152 {
10153         p->rng_fault_state = true;
10154         return WERR_NOT_SUPPORTED;
10155 }
10156
10157 /****************************************************************
10158  _spoolss_DeletePrinterConnection
10159 ****************************************************************/
10160
10161 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10162                                         struct spoolss_DeletePrinterConnection *r)
10163 {
10164         p->rng_fault_state = true;
10165         return WERR_NOT_SUPPORTED;
10166 }
10167
10168 /****************************************************************
10169  _spoolss_PrinterMessageBox
10170 ****************************************************************/
10171
10172 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10173                                   struct spoolss_PrinterMessageBox *r)
10174 {
10175         p->rng_fault_state = true;
10176         return WERR_NOT_SUPPORTED;
10177 }
10178
10179 /****************************************************************
10180  _spoolss_AddMonitor
10181 ****************************************************************/
10182
10183 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10184                            struct spoolss_AddMonitor *r)
10185 {
10186         p->rng_fault_state = true;
10187         return WERR_NOT_SUPPORTED;
10188 }
10189
10190 /****************************************************************
10191  _spoolss_DeleteMonitor
10192 ****************************************************************/
10193
10194 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10195                               struct spoolss_DeleteMonitor *r)
10196 {
10197         p->rng_fault_state = true;
10198         return WERR_NOT_SUPPORTED;
10199 }
10200
10201 /****************************************************************
10202  _spoolss_DeletePrintProcessor
10203 ****************************************************************/
10204
10205 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10206                                      struct spoolss_DeletePrintProcessor *r)
10207 {
10208         p->rng_fault_state = true;
10209         return WERR_NOT_SUPPORTED;
10210 }
10211
10212 /****************************************************************
10213  _spoolss_AddPrintProvidor
10214 ****************************************************************/
10215
10216 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10217                                  struct spoolss_AddPrintProvidor *r)
10218 {
10219         p->rng_fault_state = true;
10220         return WERR_NOT_SUPPORTED;
10221 }
10222
10223 /****************************************************************
10224  _spoolss_DeletePrintProvidor
10225 ****************************************************************/
10226
10227 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10228                                     struct spoolss_DeletePrintProvidor *r)
10229 {
10230         p->rng_fault_state = true;
10231         return WERR_NOT_SUPPORTED;
10232 }
10233
10234 /****************************************************************
10235  _spoolss_FindFirstPrinterChangeNotification
10236 ****************************************************************/
10237
10238 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10239                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10240 {
10241         p->rng_fault_state = true;
10242         return WERR_NOT_SUPPORTED;
10243 }
10244
10245 /****************************************************************
10246  _spoolss_FindNextPrinterChangeNotification
10247 ****************************************************************/
10248
10249 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10250                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10251 {
10252         p->rng_fault_state = true;
10253         return WERR_NOT_SUPPORTED;
10254 }
10255
10256 /****************************************************************
10257  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10258 ****************************************************************/
10259
10260 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10261                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10262 {
10263         p->rng_fault_state = true;
10264         return WERR_NOT_SUPPORTED;
10265 }
10266
10267 /****************************************************************
10268  _spoolss_ReplyOpenPrinter
10269 ****************************************************************/
10270
10271 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10272                                  struct spoolss_ReplyOpenPrinter *r)
10273 {
10274         p->rng_fault_state = true;
10275         return WERR_NOT_SUPPORTED;
10276 }
10277
10278 /****************************************************************
10279  _spoolss_RouterReplyPrinter
10280 ****************************************************************/
10281
10282 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10283                                    struct spoolss_RouterReplyPrinter *r)
10284 {
10285         p->rng_fault_state = true;
10286         return WERR_NOT_SUPPORTED;
10287 }
10288
10289 /****************************************************************
10290  _spoolss_ReplyClosePrinter
10291 ****************************************************************/
10292
10293 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10294                                   struct spoolss_ReplyClosePrinter *r)
10295 {
10296         p->rng_fault_state = true;
10297         return WERR_NOT_SUPPORTED;
10298 }
10299
10300 /****************************************************************
10301  _spoolss_AddPortEx
10302 ****************************************************************/
10303
10304 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10305                           struct spoolss_AddPortEx *r)
10306 {
10307         p->rng_fault_state = true;
10308         return WERR_NOT_SUPPORTED;
10309 }
10310
10311 /****************************************************************
10312  _spoolss_RouterFindFirstPrinterChangeNotification
10313 ****************************************************************/
10314
10315 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10316                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10317 {
10318         p->rng_fault_state = true;
10319         return WERR_NOT_SUPPORTED;
10320 }
10321
10322 /****************************************************************
10323  _spoolss_SpoolerInit
10324 ****************************************************************/
10325
10326 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10327                             struct spoolss_SpoolerInit *r)
10328 {
10329         p->rng_fault_state = true;
10330         return WERR_NOT_SUPPORTED;
10331 }
10332
10333 /****************************************************************
10334  _spoolss_ResetPrinterEx
10335 ****************************************************************/
10336
10337 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10338                                struct spoolss_ResetPrinterEx *r)
10339 {
10340         p->rng_fault_state = true;
10341         return WERR_NOT_SUPPORTED;
10342 }
10343
10344 /****************************************************************
10345  _spoolss_RouterReplyPrinterEx
10346 ****************************************************************/
10347
10348 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10349                                      struct spoolss_RouterReplyPrinterEx *r)
10350 {
10351         p->rng_fault_state = true;
10352         return WERR_NOT_SUPPORTED;
10353 }
10354
10355 /****************************************************************
10356  _spoolss_44
10357 ****************************************************************/
10358
10359 WERROR _spoolss_44(struct pipes_struct *p,
10360                    struct spoolss_44 *r)
10361 {
10362         p->rng_fault_state = true;
10363         return WERR_NOT_SUPPORTED;
10364 }
10365
10366 /****************************************************************
10367  _spoolss_SetPort
10368 ****************************************************************/
10369
10370 WERROR _spoolss_SetPort(struct pipes_struct *p,
10371                         struct spoolss_SetPort *r)
10372 {
10373         p->rng_fault_state = true;
10374         return WERR_NOT_SUPPORTED;
10375 }
10376
10377 /****************************************************************
10378  _spoolss_4a
10379 ****************************************************************/
10380
10381 WERROR _spoolss_4a(struct pipes_struct *p,
10382                    struct spoolss_4a *r)
10383 {
10384         p->rng_fault_state = true;
10385         return WERR_NOT_SUPPORTED;
10386 }
10387
10388 /****************************************************************
10389  _spoolss_4b
10390 ****************************************************************/
10391
10392 WERROR _spoolss_4b(struct pipes_struct *p,
10393                    struct spoolss_4b *r)
10394 {
10395         p->rng_fault_state = true;
10396         return WERR_NOT_SUPPORTED;
10397 }
10398
10399 /****************************************************************
10400  _spoolss_4c
10401 ****************************************************************/
10402
10403 WERROR _spoolss_4c(struct pipes_struct *p,
10404                    struct spoolss_4c *r)
10405 {
10406         p->rng_fault_state = true;
10407         return WERR_NOT_SUPPORTED;
10408 }
10409
10410 /****************************************************************
10411  _spoolss_53
10412 ****************************************************************/
10413
10414 WERROR _spoolss_53(struct pipes_struct *p,
10415                    struct spoolss_53 *r)
10416 {
10417         p->rng_fault_state = true;
10418         return WERR_NOT_SUPPORTED;
10419 }
10420
10421 /****************************************************************
10422  _spoolss_AddPerMachineConnection
10423 ****************************************************************/
10424
10425 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10426                                         struct spoolss_AddPerMachineConnection *r)
10427 {
10428         p->rng_fault_state = true;
10429         return WERR_NOT_SUPPORTED;
10430 }
10431
10432 /****************************************************************
10433  _spoolss_DeletePerMachineConnection
10434 ****************************************************************/
10435
10436 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10437                                            struct spoolss_DeletePerMachineConnection *r)
10438 {
10439         p->rng_fault_state = true;
10440         return WERR_NOT_SUPPORTED;
10441 }
10442
10443 /****************************************************************
10444  _spoolss_EnumPerMachineConnections
10445 ****************************************************************/
10446
10447 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10448                                           struct spoolss_EnumPerMachineConnections *r)
10449 {
10450         p->rng_fault_state = true;
10451         return WERR_NOT_SUPPORTED;
10452 }
10453
10454 /****************************************************************
10455  _spoolss_5a
10456 ****************************************************************/
10457
10458 WERROR _spoolss_5a(struct pipes_struct *p,
10459                    struct spoolss_5a *r)
10460 {
10461         p->rng_fault_state = true;
10462         return WERR_NOT_SUPPORTED;
10463 }
10464
10465 /****************************************************************
10466  _spoolss_5b
10467 ****************************************************************/
10468
10469 WERROR _spoolss_5b(struct pipes_struct *p,
10470                    struct spoolss_5b *r)
10471 {
10472         p->rng_fault_state = true;
10473         return WERR_NOT_SUPPORTED;
10474 }
10475
10476 /****************************************************************
10477  _spoolss_5c
10478 ****************************************************************/
10479
10480 WERROR _spoolss_5c(struct pipes_struct *p,
10481                    struct spoolss_5c *r)
10482 {
10483         p->rng_fault_state = true;
10484         return WERR_NOT_SUPPORTED;
10485 }
10486
10487 /****************************************************************
10488  _spoolss_5d
10489 ****************************************************************/
10490
10491 WERROR _spoolss_5d(struct pipes_struct *p,
10492                    struct spoolss_5d *r)
10493 {
10494         p->rng_fault_state = true;
10495         return WERR_NOT_SUPPORTED;
10496 }
10497
10498 /****************************************************************
10499  _spoolss_5e
10500 ****************************************************************/
10501
10502 WERROR _spoolss_5e(struct pipes_struct *p,
10503                    struct spoolss_5e *r)
10504 {
10505         p->rng_fault_state = true;
10506         return WERR_NOT_SUPPORTED;
10507 }
10508
10509 /****************************************************************
10510  _spoolss_5f
10511 ****************************************************************/
10512
10513 WERROR _spoolss_5f(struct pipes_struct *p,
10514                    struct spoolss_5f *r)
10515 {
10516         p->rng_fault_state = true;
10517         return WERR_NOT_SUPPORTED;
10518 }
10519
10520 /****************************************************************
10521  _spoolss_60
10522 ****************************************************************/
10523
10524 WERROR _spoolss_60(struct pipes_struct *p,
10525                    struct spoolss_60 *r)
10526 {
10527         p->rng_fault_state = true;
10528         return WERR_NOT_SUPPORTED;
10529 }
10530
10531 /****************************************************************
10532  _spoolss_61
10533 ****************************************************************/
10534
10535 WERROR _spoolss_61(struct pipes_struct *p,
10536                    struct spoolss_61 *r)
10537 {
10538         p->rng_fault_state = true;
10539         return WERR_NOT_SUPPORTED;
10540 }
10541
10542 /****************************************************************
10543  _spoolss_62
10544 ****************************************************************/
10545
10546 WERROR _spoolss_62(struct pipes_struct *p,
10547                    struct spoolss_62 *r)
10548 {
10549         p->rng_fault_state = true;
10550         return WERR_NOT_SUPPORTED;
10551 }
10552
10553 /****************************************************************
10554  _spoolss_63
10555 ****************************************************************/
10556
10557 WERROR _spoolss_63(struct pipes_struct *p,
10558                    struct spoolss_63 *r)
10559 {
10560         p->rng_fault_state = true;
10561         return WERR_NOT_SUPPORTED;
10562 }
10563
10564 /****************************************************************
10565  _spoolss_64
10566 ****************************************************************/
10567
10568 WERROR _spoolss_64(struct pipes_struct *p,
10569                    struct spoolss_64 *r)
10570 {
10571         p->rng_fault_state = true;
10572         return WERR_NOT_SUPPORTED;
10573 }
10574
10575 /****************************************************************
10576  _spoolss_65
10577 ****************************************************************/
10578
10579 WERROR _spoolss_65(struct pipes_struct *p,
10580                    struct spoolss_65 *r)
10581 {
10582         p->rng_fault_state = true;
10583         return WERR_NOT_SUPPORTED;
10584 }
10585
10586 /****************************************************************
10587  _spoolss_GetCorePrinterDrivers
10588 ****************************************************************/
10589
10590 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10591                                       struct spoolss_GetCorePrinterDrivers *r)
10592 {
10593         p->rng_fault_state = true;
10594         return WERR_NOT_SUPPORTED;
10595 }
10596
10597 /****************************************************************
10598  _spoolss_67
10599 ****************************************************************/
10600
10601 WERROR _spoolss_67(struct pipes_struct *p,
10602                    struct spoolss_67 *r)
10603 {
10604         p->rng_fault_state = true;
10605         return WERR_NOT_SUPPORTED;
10606 }
10607
10608 /****************************************************************
10609  _spoolss_GetPrinterDriverPackagePath
10610 ****************************************************************/
10611
10612 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10613                                             struct spoolss_GetPrinterDriverPackagePath *r)
10614 {
10615         p->rng_fault_state = true;
10616         return WERR_NOT_SUPPORTED;
10617 }
10618
10619 /****************************************************************
10620  _spoolss_69
10621 ****************************************************************/
10622
10623 WERROR _spoolss_69(struct pipes_struct *p,
10624                    struct spoolss_69 *r)
10625 {
10626         p->rng_fault_state = true;
10627         return WERR_NOT_SUPPORTED;
10628 }
10629
10630 /****************************************************************
10631  _spoolss_6a
10632 ****************************************************************/
10633
10634 WERROR _spoolss_6a(struct pipes_struct *p,
10635                    struct spoolss_6a *r)
10636 {
10637         p->rng_fault_state = true;
10638         return WERR_NOT_SUPPORTED;
10639 }
10640
10641 /****************************************************************
10642  _spoolss_6b
10643 ****************************************************************/
10644
10645 WERROR _spoolss_6b(struct pipes_struct *p,
10646                    struct spoolss_6b *r)
10647 {
10648         p->rng_fault_state = true;
10649         return WERR_NOT_SUPPORTED;
10650 }
10651
10652 /****************************************************************
10653  _spoolss_6c
10654 ****************************************************************/
10655
10656 WERROR _spoolss_6c(struct pipes_struct *p,
10657                    struct spoolss_6c *r)
10658 {
10659         p->rng_fault_state = true;
10660         return WERR_NOT_SUPPORTED;
10661 }
10662
10663 /****************************************************************
10664  _spoolss_6d
10665 ****************************************************************/
10666
10667 WERROR _spoolss_6d(struct pipes_struct *p,
10668                    struct spoolss_6d *r)
10669 {
10670         p->rng_fault_state = true;
10671         return WERR_NOT_SUPPORTED;
10672 }