s3-auth Rename auth_serversupplied_info varaiables: server_info -> session_info
[ddiss/samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "librpc/gen_ndr/messaging.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
46 /* macros stolen from s4 spoolss server */
47 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
48         ((info)?ndr_size_##fn(info, level, 0):0)
49
50 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
51         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
52
53 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
54         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
55
56 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
57
58 #undef DBGC_CLASS
59 #define DBGC_CLASS DBGC_RPC_SRV
60
61 #ifndef MAX_OPEN_PRINTER_EXS
62 #define MAX_OPEN_PRINTER_EXS 50
63 #endif
64
65 struct notify_back_channel;
66
67 /* structure to store the printer handles */
68 /* and a reference to what it's pointing to */
69 /* and the notify info asked about */
70 /* that's the central struct */
71 struct printer_handle {
72         struct printer_handle *prev, *next;
73         bool document_started;
74         bool page_started;
75         uint32 jobid; /* jobid in printing backend */
76         int printer_type;
77         const char *servername;
78         fstring sharename;
79         uint32 type;
80         uint32 access_granted;
81         struct {
82                 uint32 flags;
83                 uint32 options;
84                 fstring localmachine;
85                 uint32 printerlocal;
86                 struct spoolss_NotifyOption *option;
87                 struct policy_handle cli_hnd;
88                 struct notify_back_channel *cli_chan;
89                 uint32 change;
90                 /* are we in a FindNextPrinterChangeNotify() call? */
91                 bool fnpcn;
92                 struct messaging_context *msg_ctx;
93         } notify;
94         struct {
95                 fstring machine;
96                 fstring user;
97         } client;
98
99         /* devmode sent in the OpenPrinter() call */
100         struct spoolss_DeviceMode *devmode;
101
102         /* TODO cache the printer info2 structure */
103         struct spoolss_PrinterInfo2 *info2;
104
105 };
106
107 static struct printer_handle *printers_list;
108
109 struct printer_session_counter {
110         struct printer_session_counter *next;
111         struct printer_session_counter *prev;
112
113         int snum;
114         uint32_t counter;
115 };
116
117 static struct printer_session_counter *counter_list;
118
119 struct notify_back_channel {
120         struct notify_back_channel *prev, *next;
121
122         /* associated client */
123         struct sockaddr_storage client_address;
124
125         /* print notify back-channel pipe handle*/
126         struct rpc_pipe_client *cli_pipe;
127         struct dcerpc_binding_handle *binding_handle;
128         uint32_t active_connections;
129 };
130
131 static struct notify_back_channel *back_channels;
132
133 /* Map generic permissions to printer object specific permissions */
134
135 const struct standard_mapping printer_std_mapping = {
136         PRINTER_READ,
137         PRINTER_WRITE,
138         PRINTER_EXECUTE,
139         PRINTER_ALL_ACCESS
140 };
141
142 /* Map generic permissions to print server object specific permissions */
143
144 const struct standard_mapping printserver_std_mapping = {
145         SERVER_READ,
146         SERVER_WRITE,
147         SERVER_EXECUTE,
148         SERVER_ALL_ACCESS
149 };
150
151 /* API table for Xcv Monitor functions */
152
153 struct xcv_api_table {
154         const char *name;
155         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
156 };
157
158 static void prune_printername_cache(void);
159
160 /********************************************************************
161  * Canonicalize servername.
162  ********************************************************************/
163
164 static const char *canon_servername(const char *servername)
165 {
166         const char *pservername = servername;
167         while (*pservername == '\\') {
168                 pservername++;
169         }
170         return pservername;
171 }
172
173 /* translate between internal status numbers and NT status numbers */
174 static int nt_printj_status(int v)
175 {
176         switch (v) {
177         case LPQ_QUEUED:
178                 return 0;
179         case LPQ_PAUSED:
180                 return JOB_STATUS_PAUSED;
181         case LPQ_SPOOLING:
182                 return JOB_STATUS_SPOOLING;
183         case LPQ_PRINTING:
184                 return JOB_STATUS_PRINTING;
185         case LPQ_ERROR:
186                 return JOB_STATUS_ERROR;
187         case LPQ_DELETING:
188                 return JOB_STATUS_DELETING;
189         case LPQ_OFFLINE:
190                 return JOB_STATUS_OFFLINE;
191         case LPQ_PAPEROUT:
192                 return JOB_STATUS_PAPEROUT;
193         case LPQ_PRINTED:
194                 return JOB_STATUS_PRINTED;
195         case LPQ_DELETED:
196                 return JOB_STATUS_DELETED;
197         case LPQ_BLOCKED:
198                 return JOB_STATUS_BLOCKED_DEVQ;
199         case LPQ_USER_INTERVENTION:
200                 return JOB_STATUS_USER_INTERVENTION;
201         }
202         return 0;
203 }
204
205 static int nt_printq_status(int v)
206 {
207         switch (v) {
208         case LPQ_PAUSED:
209                 return PRINTER_STATUS_PAUSED;
210         case LPQ_QUEUED:
211         case LPQ_SPOOLING:
212         case LPQ_PRINTING:
213                 return 0;
214         }
215         return 0;
216 }
217
218 /***************************************************************************
219  Disconnect from the client
220 ****************************************************************************/
221
222 static void srv_spoolss_replycloseprinter(int snum,
223                                           struct printer_handle *prn_hnd)
224 {
225         WERROR result;
226         NTSTATUS status;
227
228         /*
229          * Tell the specific printing tdb we no longer want messages for this printer
230          * by deregistering our PID.
231          */
232
233         if (!print_notify_deregister_pid(snum)) {
234                 DEBUG(0, ("Failed to register our pid for printer %s\n",
235                           lp_const_servicename(snum)));
236         }
237
238         /* weird if the test succeeds !!! */
239         if (prn_hnd->notify.cli_chan == NULL ||
240             prn_hnd->notify.cli_chan->active_connections == 0) {
241                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
242                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
243                 TALLOC_FREE(prn_hnd->notify.cli_chan);
244                 return;
245         }
246
247         status = dcerpc_spoolss_ReplyClosePrinter(
248                                         prn_hnd->notify.cli_chan->binding_handle,
249                                         talloc_tos(),
250                                         &prn_hnd->notify.cli_hnd,
251                                         &result);
252         if (!NT_STATUS_IS_OK(status)) {
253                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
254                           nt_errstr(status)));
255                 result = ntstatus_to_werror(status);
256         } else if (!W_ERROR_IS_OK(result)) {
257                 DEBUG(0, ("reply_close_printer failed [%s].\n",
258                           win_errstr(result)));
259         }
260
261         /* if it's the last connection, deconnect the IPC$ share */
262         if (prn_hnd->notify.cli_chan->active_connections == 1) {
263
264                 prn_hnd->notify.cli_chan->binding_handle = NULL;
265                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
266                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
267                 TALLOC_FREE(prn_hnd->notify.cli_chan);
268
269                 if (prn_hnd->notify.msg_ctx != NULL) {
270                         messaging_deregister(prn_hnd->notify.msg_ctx,
271                                              MSG_PRINTER_NOTIFY2, NULL);
272
273                         /*
274                          * Tell the serverid.tdb we're no longer
275                          * interested in printer notify messages.
276                          */
277
278                         serverid_register_msg_flags(
279                                 messaging_server_id(prn_hnd->notify.msg_ctx),
280                                 false, FLAG_MSG_PRINT_NOTIFY);
281                 }
282         }
283
284         if (prn_hnd->notify.cli_chan) {
285                 prn_hnd->notify.cli_chan->active_connections--;
286         }
287 }
288
289 /****************************************************************************
290  Functions to free a printer entry datastruct.
291 ****************************************************************************/
292
293 static int printer_entry_destructor(struct printer_handle *Printer)
294 {
295         if (Printer->notify.cli_chan != NULL &&
296             Printer->notify.cli_chan->active_connections > 0) {
297                 int snum = -1;
298
299                 switch(Printer->printer_type) {
300                 case SPLHND_SERVER:
301                         srv_spoolss_replycloseprinter(snum, Printer);
302                         break;
303
304                 case SPLHND_PRINTER:
305                         snum = print_queue_snum(Printer->sharename);
306                         if (snum != -1) {
307                                 srv_spoolss_replycloseprinter(snum, Printer);
308                         }
309                         break;
310                 default:
311                         break;
312                 }
313         }
314
315         Printer->notify.flags=0;
316         Printer->notify.options=0;
317         Printer->notify.localmachine[0]='\0';
318         Printer->notify.printerlocal=0;
319         TALLOC_FREE(Printer->notify.option);
320         TALLOC_FREE(Printer->devmode);
321
322         /* Remove from the internal list. */
323         DLIST_REMOVE(printers_list, Printer);
324         return 0;
325 }
326
327 /****************************************************************************
328   find printer index by handle
329 ****************************************************************************/
330
331 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
332                                                         struct policy_handle *hnd)
333 {
334         struct printer_handle *find_printer = NULL;
335
336         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
337                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
338                 return NULL;
339         }
340
341         return find_printer;
342 }
343
344 /****************************************************************************
345  Close printer index by handle.
346 ****************************************************************************/
347
348 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
349 {
350         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
351
352         if (!Printer) {
353                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
354                         OUR_HANDLE(hnd)));
355                 return false;
356         }
357
358         close_policy_hnd(p, hnd);
359
360         return true;
361 }
362
363 /****************************************************************************
364  Delete a printer given a handle.
365 ****************************************************************************/
366
367 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
368                                   const char *sharename,
369                                   struct messaging_context *msg_ctx)
370 {
371         char *cmd = lp_deleteprinter_cmd();
372         char *command = NULL;
373         int ret;
374         bool is_print_op = false;
375
376         /* can't fail if we don't try */
377
378         if ( !*cmd )
379                 return WERR_OK;
380
381         command = talloc_asprintf(ctx,
382                         "%s \"%s\"",
383                         cmd, sharename);
384         if (!command) {
385                 return WERR_NOMEM;
386         }
387         if ( token )
388                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
389
390         DEBUG(10,("Running [%s]\n", command));
391
392         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
393
394         if ( is_print_op )
395                 become_root();
396
397         if ( (ret = smbrun(command, NULL)) == 0 ) {
398                 /* Tell everyone we updated smb.conf. */
399                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
400         }
401
402         if ( is_print_op )
403                 unbecome_root();
404
405         /********** END SePrintOperatorPrivlege BLOCK **********/
406
407         DEBUGADD(10,("returned [%d]\n", ret));
408
409         TALLOC_FREE(command);
410
411         if (ret != 0)
412                 return WERR_BADFID; /* What to return here? */
413
414         /* go ahead and re-read the services immediately */
415         become_root();
416         reload_services(msg_ctx, -1, false);
417         unbecome_root();
418
419         if ( lp_servicenumber( sharename ) >= 0 )
420                 return WERR_ACCESS_DENIED;
421
422         return WERR_OK;
423 }
424
425 /****************************************************************************
426  Delete a printer given a handle.
427 ****************************************************************************/
428
429 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
430 {
431         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
432         WERROR result;
433
434         if (!Printer) {
435                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
436                         OUR_HANDLE(hnd)));
437                 return WERR_BADFID;
438         }
439
440         /*
441          * It turns out that Windows allows delete printer on a handle
442          * opened by an admin user, then used on a pipe handle created
443          * by an anonymous user..... but they're working on security.... riiight !
444          * JRA.
445          */
446
447         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
448                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
449                 return WERR_ACCESS_DENIED;
450         }
451
452         /* this does not need a become root since the access check has been
453            done on the handle already */
454
455         result = winreg_delete_printer_key(p->mem_ctx,
456                                            get_session_info_system(),
457                                            p->msg_ctx,
458                                            Printer->sharename,
459                                            "");
460         if (!W_ERROR_IS_OK(result)) {
461                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
462                 return WERR_BADFID;
463         }
464
465         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
466                                      Printer->sharename, p->msg_ctx);
467         if (!W_ERROR_IS_OK(result)) {
468                 return result;
469         }
470         prune_printername_cache();
471         return WERR_OK;
472 }
473
474 /****************************************************************************
475  Return the snum of a printer corresponding to an handle.
476 ****************************************************************************/
477
478 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
479                              int *number, struct share_params **params)
480 {
481         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
482
483         if (!Printer) {
484                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
485                         OUR_HANDLE(hnd)));
486                 return false;
487         }
488
489         switch (Printer->printer_type) {
490                 case SPLHND_PRINTER:
491                         DEBUG(4,("short name:%s\n", Printer->sharename));
492                         *number = print_queue_snum(Printer->sharename);
493                         return (*number != -1);
494                 case SPLHND_SERVER:
495                         return false;
496                 default:
497                         return false;
498         }
499 }
500
501 /****************************************************************************
502  Set printer handle type.
503  Check if it's \\server or \\server\printer
504 ****************************************************************************/
505
506 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
507 {
508         DEBUG(3,("Setting printer type=%s\n", handlename));
509
510         /* it's a print server */
511         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
512                 DEBUGADD(4,("Printer is a print server\n"));
513                 Printer->printer_type = SPLHND_SERVER;
514         }
515         /* it's a printer (set_printer_hnd_name() will handle port monitors */
516         else {
517                 DEBUGADD(4,("Printer is a printer\n"));
518                 Printer->printer_type = SPLHND_PRINTER;
519         }
520
521         return true;
522 }
523
524 static void prune_printername_cache_fn(const char *key, const char *value,
525                                        time_t timeout, void *private_data)
526 {
527         gencache_del(key);
528 }
529
530 static void prune_printername_cache(void)
531 {
532         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
533 }
534
535 /****************************************************************************
536  Set printer handle name..  Accept names like \\server, \\server\printer,
537  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
538  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
539  XcvDataPort() interface.
540 ****************************************************************************/
541
542 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
543                                    const struct auth_serversupplied_info *session_info,
544                                    struct messaging_context *msg_ctx,
545                                    struct printer_handle *Printer,
546                                    const char *handlename)
547 {
548         int snum;
549         int n_services=lp_numservices();
550         char *aprinter;
551         const char *printername;
552         const char *servername = NULL;
553         fstring sname;
554         bool found = false;
555         struct spoolss_PrinterInfo2 *info2 = NULL;
556         WERROR result;
557         char *p;
558
559         /*
560          * Hopefully nobody names his printers like this. Maybe \ or ,
561          * are illegal in printer names even?
562          */
563         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
564         char *cache_key;
565         char *tmp;
566
567         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
568                 (unsigned long)strlen(handlename)));
569
570         aprinter = CONST_DISCARD(char *, handlename);
571         if ( *handlename == '\\' ) {
572                 servername = canon_servername(handlename);
573                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
574                         *aprinter = '\0';
575                         aprinter++;
576                 }
577                 if (!is_myname_or_ipaddr(servername)) {
578                         return WERR_INVALID_PRINTER_NAME;
579                 }
580                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
581                 if (Printer->servername == NULL) {
582                         return WERR_NOMEM;
583                 }
584         }
585
586         if (Printer->printer_type == SPLHND_SERVER) {
587                 return WERR_OK;
588         }
589
590         if (Printer->printer_type != SPLHND_PRINTER) {
591                 return WERR_INVALID_HANDLE;
592         }
593
594         DEBUGADD(5, ("searching for [%s]\n", aprinter));
595
596         p = strchr(aprinter, ',');
597         if (p != NULL) {
598                 char *p2 = p;
599                 p++;
600                 if (*p == ' ') {
601                         p++;
602                 }
603                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
604                         *p2 = '\0';
605                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
606                         *p2 = '\0';
607                 }
608         }
609
610         if (p) {
611                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
612         }
613
614         /* check for the Port Monitor Interface */
615         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
616                 Printer->printer_type = SPLHND_PORTMON_TCP;
617                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
618                 found = true;
619         }
620         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
621                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
622                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
623                 found = true;
624         }
625
626         /*
627          * With hundreds of printers, the "for" loop iterating all
628          * shares can be quite expensive, as it is done on every
629          * OpenPrinter. The loop maps "aprinter" to "sname", the
630          * result of which we cache in gencache.
631          */
632
633         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
634                                     aprinter);
635         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
636
637                 found = (strcmp(tmp, printer_not_found) != 0);
638                 if (!found) {
639                         DEBUG(4, ("Printer %s not found\n", aprinter));
640                         SAFE_FREE(tmp);
641                         return WERR_INVALID_PRINTER_NAME;
642                 }
643                 fstrcpy(sname, tmp);
644                 SAFE_FREE(tmp);
645         }
646
647         /* Search all sharenames first as this is easier than pulling
648            the printer_info_2 off of disk. Don't use find_service() since
649            that calls out to map_username() */
650
651         /* do another loop to look for printernames */
652         for (snum = 0; !found && snum < n_services; snum++) {
653                 const char *printer = lp_const_servicename(snum);
654
655                 /* no point going on if this is not a printer */
656                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
657                         continue;
658                 }
659
660                 /* ignore [printers] share */
661                 if (strequal(printer, "printers")) {
662                         continue;
663                 }
664
665                 fstrcpy(sname, printer);
666                 if (strequal(aprinter, printer)) {
667                         found = true;
668                         break;
669                 }
670
671                 /* no point looking up the printer object if
672                    we aren't allowing printername != sharename */
673                 if (lp_force_printername(snum)) {
674                         continue;
675                 }
676
677                 result = winreg_get_printer(mem_ctx,
678                                             session_info,
679                                             msg_ctx,
680                                             sname,
681                                             &info2);
682                 if ( !W_ERROR_IS_OK(result) ) {
683                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
684                                  sname, win_errstr(result)));
685                         continue;
686                 }
687
688                 printername = strrchr(info2->printername, '\\');
689                 if (printername == NULL) {
690                         printername = info2->printername;
691                 } else {
692                         printername++;
693                 }
694
695                 if (strequal(printername, aprinter)) {
696                         found = true;
697                         break;
698                 }
699
700                 DEBUGADD(10, ("printername: %s\n", printername));
701
702                 TALLOC_FREE(info2);
703         }
704
705         if ( !found ) {
706                 if (cache_key != NULL) {
707                         gencache_set(cache_key, printer_not_found,
708                                      time(NULL)+300);
709                         TALLOC_FREE(cache_key);
710                 }
711                 DEBUGADD(4,("Printer not found\n"));
712                 return WERR_INVALID_PRINTER_NAME;
713         }
714
715         if (cache_key != NULL) {
716                 gencache_set(cache_key, sname, time(NULL)+300);
717                 TALLOC_FREE(cache_key);
718         }
719
720         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
721
722         fstrcpy(Printer->sharename, sname);
723
724         return WERR_OK;
725 }
726
727 /****************************************************************************
728  Find first available printer slot. creates a printer handle for you.
729  ****************************************************************************/
730
731 static WERROR open_printer_hnd(struct pipes_struct *p,
732                                struct policy_handle *hnd,
733                                const char *name,
734                                uint32_t access_granted)
735 {
736         struct printer_handle *new_printer;
737         WERROR result;
738
739         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
740
741         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
742         if (new_printer == NULL) {
743                 return WERR_NOMEM;
744         }
745         talloc_set_destructor(new_printer, printer_entry_destructor);
746
747         /* This also steals the printer_handle on the policy_handle */
748         if (!create_policy_hnd(p, hnd, new_printer)) {
749                 TALLOC_FREE(new_printer);
750                 return WERR_INVALID_HANDLE;
751         }
752
753         /* Add to the internal list. */
754         DLIST_ADD(printers_list, new_printer);
755
756         new_printer->notify.option=NULL;
757
758         if (!set_printer_hnd_printertype(new_printer, name)) {
759                 close_printer_handle(p, hnd);
760                 return WERR_INVALID_HANDLE;
761         }
762
763         result = set_printer_hnd_name(p->mem_ctx,
764                                       get_session_info_system(),
765                                       p->msg_ctx,
766                                       new_printer, name);
767         if (!W_ERROR_IS_OK(result)) {
768                 close_printer_handle(p, hnd);
769                 return result;
770         }
771
772         new_printer->access_granted = access_granted;
773
774         DEBUG(5, ("%d printer handles active\n",
775                   (int)num_pipe_handles(p)));
776
777         return WERR_OK;
778 }
779
780 /***************************************************************************
781  check to see if the client motify handle is monitoring the notification
782  given by (notify_type, notify_field).
783  **************************************************************************/
784
785 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
786                                       uint16_t notify_field)
787 {
788         return true;
789 }
790
791 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
792                                 uint16_t notify_field)
793 {
794         struct spoolss_NotifyOption *option = p->notify.option;
795         uint32_t i, j;
796
797         /*
798          * Flags should always be zero when the change notify
799          * is registered by the client's spooler.  A user Win32 app
800          * might use the flags though instead of the NOTIFY_OPTION_INFO
801          * --jerry
802          */
803
804         if (!option) {
805                 return false;
806         }
807
808         if (p->notify.flags)
809                 return is_monitoring_event_flags(
810                         p->notify.flags, notify_type, notify_field);
811
812         for (i = 0; i < option->count; i++) {
813
814                 /* Check match for notify_type */
815
816                 if (option->types[i].type != notify_type)
817                         continue;
818
819                 /* Check match for field */
820
821                 for (j = 0; j < option->types[i].count; j++) {
822                         if (option->types[i].fields[j].field == notify_field) {
823                                 return true;
824                         }
825                 }
826         }
827
828         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
829                    p->servername, p->sharename, notify_type, notify_field));
830
831         return false;
832 }
833
834 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
835         _data->data.integer[0] = _integer; \
836         _data->data.integer[1] = 0;
837
838
839 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
840         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
841         if (!_data->data.string.string) {\
842                 _data->data.string.size = 0; \
843         } \
844         _data->data.string.size = strlen_m_term(_p) * 2;
845
846 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
847         _data->data.devmode.devmode = _devmode;
848
849 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
850         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
851         if (!_data->data.sd.sd) { \
852                 _data->data.sd.sd_size = 0; \
853         } \
854         _data->data.sd.sd_size = \
855                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
856
857 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
858                                    struct tm *t,
859                                    const char **pp,
860                                    uint32_t *plen)
861 {
862         struct spoolss_Time st;
863         uint32_t len = 16;
864         char *p;
865
866         if (!init_systemtime(&st, t)) {
867                 return;
868         }
869
870         p = talloc_array(mem_ctx, char, len);
871         if (!p) {
872                 return;
873         }
874
875         /*
876          * Systemtime must be linearized as a set of UINT16's.
877          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
878          */
879
880         SSVAL(p, 0, st.year);
881         SSVAL(p, 2, st.month);
882         SSVAL(p, 4, st.day_of_week);
883         SSVAL(p, 6, st.day);
884         SSVAL(p, 8, st.hour);
885         SSVAL(p, 10, st.minute);
886         SSVAL(p, 12, st.second);
887         SSVAL(p, 14, st.millisecond);
888
889         *pp = p;
890         *plen = len;
891 }
892
893 /* Convert a notification message to a struct spoolss_Notify */
894
895 static void notify_one_value(struct spoolss_notify_msg *msg,
896                              struct spoolss_Notify *data,
897                              TALLOC_CTX *mem_ctx)
898 {
899         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
900 }
901
902 static void notify_string(struct spoolss_notify_msg *msg,
903                           struct spoolss_Notify *data,
904                           TALLOC_CTX *mem_ctx)
905 {
906         /* The length of the message includes the trailing \0 */
907
908         data->data.string.size = msg->len * 2;
909         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
910         if (!data->data.string.string) {
911                 data->data.string.size = 0;
912                 return;
913         }
914 }
915
916 static void notify_system_time(struct spoolss_notify_msg *msg,
917                                struct spoolss_Notify *data,
918                                TALLOC_CTX *mem_ctx)
919 {
920         data->data.string.string = NULL;
921         data->data.string.size = 0;
922
923         if (msg->len != sizeof(time_t)) {
924                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
925                           msg->len));
926                 return;
927         }
928
929         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
930                                &data->data.string.string,
931                                &data->data.string.size);
932 }
933
934 struct notify2_message_table {
935         const char *name;
936         void (*fn)(struct spoolss_notify_msg *msg,
937                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
938 };
939
940 static struct notify2_message_table printer_notify_table[] = {
941         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
942         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
943         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
944         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
945         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
946         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
947         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
948         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
949         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
950         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
951         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
952         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
953         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
954         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
955         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
956         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
957         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
958         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
959         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
960 };
961
962 static struct notify2_message_table job_notify_table[] = {
963         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
964         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
965         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
966         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
967         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
968         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
969         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
970         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
971         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
972         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
973         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
974         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
975         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
976         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
977         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
978         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
979         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
980         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
981         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
982         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
983         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
984         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
985         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
986         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
987 };
988
989
990 /***********************************************************************
991  Allocate talloc context for container object
992  **********************************************************************/
993
994 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
995 {
996         if ( !ctr )
997                 return;
998
999         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1000
1001         return;
1002 }
1003
1004 /***********************************************************************
1005  release all allocated memory and zero out structure
1006  **********************************************************************/
1007
1008 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1009 {
1010         if ( !ctr )
1011                 return;
1012
1013         if ( ctr->ctx )
1014                 talloc_destroy(ctr->ctx);
1015
1016         ZERO_STRUCTP(ctr);
1017
1018         return;
1019 }
1020
1021 /***********************************************************************
1022  **********************************************************************/
1023
1024 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1025 {
1026         if ( !ctr )
1027                 return NULL;
1028
1029         return ctr->ctx;
1030 }
1031
1032 /***********************************************************************
1033  **********************************************************************/
1034
1035 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1036 {
1037         if ( !ctr || !ctr->msg_groups )
1038                 return NULL;
1039
1040         if ( idx >= ctr->num_groups )
1041                 return NULL;
1042
1043         return &ctr->msg_groups[idx];
1044
1045 }
1046
1047 /***********************************************************************
1048  How many groups of change messages do we have ?
1049  **********************************************************************/
1050
1051 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1052 {
1053         if ( !ctr )
1054                 return 0;
1055
1056         return ctr->num_groups;
1057 }
1058
1059 /***********************************************************************
1060  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1061  **********************************************************************/
1062
1063 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1064 {
1065         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1066         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1067         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1068         int                             i, new_slot;
1069
1070         if ( !ctr || !msg )
1071                 return 0;
1072
1073         /* loop over all groups looking for a matching printer name */
1074
1075         for ( i=0; i<ctr->num_groups; i++ ) {
1076                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1077                         break;
1078         }
1079
1080         /* add a new group? */
1081
1082         if ( i == ctr->num_groups ) {
1083                 ctr->num_groups++;
1084
1085                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1086                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1087                         return 0;
1088                 }
1089                 ctr->msg_groups = groups;
1090
1091                 /* clear the new entry and set the printer name */
1092
1093                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1094                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1095         }
1096
1097         /* add the change messages; 'i' is the correct index now regardless */
1098
1099         msg_grp = &ctr->msg_groups[i];
1100
1101         msg_grp->num_msgs++;
1102
1103         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1104                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1105                 return 0;
1106         }
1107         msg_grp->msgs = msg_list;
1108
1109         new_slot = msg_grp->num_msgs-1;
1110         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1111
1112         /* need to allocate own copy of data */
1113
1114         if ( msg->len != 0 )
1115                 msg_grp->msgs[new_slot].notify.data = (char *)
1116                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1117
1118         return ctr->num_groups;
1119 }
1120
1121 static void construct_info_data(struct spoolss_Notify *info_data,
1122                                 enum spoolss_NotifyType type,
1123                                 uint16_t field, int id);
1124
1125 /***********************************************************************
1126  Send a change notication message on all handles which have a call
1127  back registered
1128  **********************************************************************/
1129
1130 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1131                                   struct printer_handle *prn_hnd,
1132                                   SPOOLSS_NOTIFY_MSG *messages,
1133                                   uint32_t num_msgs,
1134                                   struct spoolss_Notify **_notifies,
1135                                   int *_count)
1136 {
1137         struct spoolss_Notify *notifies;
1138         SPOOLSS_NOTIFY_MSG *msg;
1139         int count = 0;
1140         uint32_t id;
1141         int i;
1142
1143         notifies = talloc_zero_array(mem_ctx,
1144                                      struct spoolss_Notify, num_msgs);
1145         if (!notifies) {
1146                 return ENOMEM;
1147         }
1148
1149         for (i = 0; i < num_msgs; i++) {
1150
1151                 msg = &messages[i];
1152
1153                 /* Are we monitoring this event? */
1154
1155                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1156                         continue;
1157                 }
1158
1159                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1160                            "for printer [%s]\n",
1161                            msg->type, msg->field, prn_hnd->sharename));
1162
1163                 /*
1164                  * if the is a printer notification handle and not a job
1165                  * notification type, then set the id to 0.
1166                  * Otherwise just use what was specified in the message.
1167                  *
1168                  * When registering change notification on a print server
1169                  * handle we always need to send back the id (snum) matching
1170                  * the printer for which the change took place.
1171                  * For change notify registered on a printer handle,
1172                  * this does not matter and the id should be 0.
1173                  *
1174                  * --jerry
1175                  */
1176
1177                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1178                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1179                         id = 0;
1180                 } else {
1181                         id = msg->id;
1182                 }
1183
1184                 /* Convert unix jobid to smb jobid */
1185
1186                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1187                         id = sysjob_to_jobid(msg->id);
1188
1189                         if (id == -1) {
1190                                 DEBUG(3, ("no such unix jobid %d\n",
1191                                           msg->id));
1192                                 continue;
1193                         }
1194                 }
1195
1196                 construct_info_data(&notifies[count],
1197                                     msg->type, msg->field, id);
1198
1199                 switch(msg->type) {
1200                 case PRINTER_NOTIFY_TYPE:
1201                         if (printer_notify_table[msg->field].fn) {
1202                                 printer_notify_table[msg->field].fn(msg,
1203                                                 &notifies[count], mem_ctx);
1204                         }
1205                         break;
1206
1207                 case JOB_NOTIFY_TYPE:
1208                         if (job_notify_table[msg->field].fn) {
1209                                 job_notify_table[msg->field].fn(msg,
1210                                                 &notifies[count], mem_ctx);
1211                         }
1212                         break;
1213
1214                 default:
1215                         DEBUG(5, ("Unknown notification type %d\n",
1216                                   msg->type));
1217                         continue;
1218                 }
1219
1220                 count++;
1221         }
1222
1223         *_notifies = notifies;
1224         *_count = count;
1225
1226         return 0;
1227 }
1228
1229 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1230                                 struct printer_handle *prn_hnd,
1231                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1232 {
1233         struct spoolss_Notify *notifies;
1234         int count = 0;
1235         union spoolss_ReplyPrinterInfo info;
1236         struct spoolss_NotifyInfo info0;
1237         uint32_t reply_result;
1238         NTSTATUS status;
1239         WERROR werr;
1240         int ret;
1241
1242         /* Is there notification on this handle? */
1243         if (prn_hnd->notify.cli_chan == NULL ||
1244             prn_hnd->notify.cli_chan->active_connections == 0) {
1245                 return 0;
1246         }
1247
1248         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1249                    prn_hnd->servername, prn_hnd->sharename));
1250
1251         /* For this printer? Print servers always receive notifications. */
1252         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1253             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1254                 return 0;
1255         }
1256
1257         DEBUG(10,("Our printer\n"));
1258
1259         /* build the array of change notifications */
1260         ret = build_notify2_messages(mem_ctx, prn_hnd,
1261                                      msg_group->msgs,
1262                                      msg_group->num_msgs,
1263                                      &notifies, &count);
1264         if (ret) {
1265                 return ret;
1266         }
1267
1268         info0.version   = 0x2;
1269         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1270         info0.count     = count;
1271         info0.notifies  = notifies;
1272
1273         info.info0 = &info0;
1274
1275         status = dcerpc_spoolss_RouterReplyPrinterEx(
1276                                 prn_hnd->notify.cli_chan->binding_handle,
1277                                 mem_ctx,
1278                                 &prn_hnd->notify.cli_hnd,
1279                                 prn_hnd->notify.change, /* color */
1280                                 prn_hnd->notify.flags,
1281                                 &reply_result,
1282                                 0, /* reply_type, must be 0 */
1283                                 info, &werr);
1284         if (!NT_STATUS_IS_OK(status)) {
1285                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1286                           "failed: %s\n",
1287                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1288                           nt_errstr(status)));
1289                 werr = ntstatus_to_werror(status);
1290         } else if (!W_ERROR_IS_OK(werr)) {
1291                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1292                           "failed: %s\n",
1293                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1294                           win_errstr(werr)));
1295         }
1296         switch (reply_result) {
1297         case 0:
1298                 break;
1299         case PRINTER_NOTIFY_INFO_DISCARDED:
1300         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1301         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1302                 break;
1303         default:
1304                 break;
1305         }
1306
1307         return 0;
1308 }
1309
1310 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1311 {
1312         struct printer_handle    *p;
1313         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1314         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1315         int ret;
1316
1317         if ( !msg_group ) {
1318                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1319                 return;
1320         }
1321
1322         if (!msg_group->msgs) {
1323                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1324                 return;
1325         }
1326
1327         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1328
1329         /* loop over all printers */
1330
1331         for (p = printers_list; p; p = p->next) {
1332                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1333                 if (ret) {
1334                         goto done;
1335                 }
1336         }
1337
1338 done:
1339         DEBUG(8,("send_notify2_changes: Exit...\n"));
1340         return;
1341 }
1342
1343 /***********************************************************************
1344  **********************************************************************/
1345
1346 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1347 {
1348
1349         uint32_t tv_sec, tv_usec;
1350         size_t offset = 0;
1351
1352         /* Unpack message */
1353
1354         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1355                              msg->printer);
1356
1357         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1358                                 &tv_sec, &tv_usec,
1359                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1360
1361         if (msg->len == 0)
1362                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1363                            &msg->notify.value[0], &msg->notify.value[1]);
1364         else
1365                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1366                            &msg->len, &msg->notify.data);
1367
1368         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1369                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1370
1371         tv->tv_sec = tv_sec;
1372         tv->tv_usec = tv_usec;
1373
1374         if (msg->len == 0)
1375                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1376                           msg->notify.value[1]));
1377         else
1378                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1379
1380         return true;
1381 }
1382
1383 /********************************************************************
1384  Receive a notify2 message list
1385  ********************************************************************/
1386
1387 static void receive_notify2_message_list(struct messaging_context *msg,
1388                                          void *private_data,
1389                                          uint32_t msg_type,
1390                                          struct server_id server_id,
1391                                          DATA_BLOB *data)
1392 {
1393         size_t                  msg_count, i;
1394         char                    *buf = (char *)data->data;
1395         char                    *msg_ptr;
1396         size_t                  msg_len;
1397         SPOOLSS_NOTIFY_MSG      notify;
1398         SPOOLSS_NOTIFY_MSG_CTR  messages;
1399         int                     num_groups;
1400
1401         if (data->length < 4) {
1402                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1403                 return;
1404         }
1405
1406         msg_count = IVAL(buf, 0);
1407         msg_ptr = buf + 4;
1408
1409         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1410
1411         if (msg_count == 0) {
1412                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1413                 return;
1414         }
1415
1416         /* initialize the container */
1417
1418         ZERO_STRUCT( messages );
1419         notify_msg_ctr_init( &messages );
1420
1421         /*
1422          * build message groups for each printer identified
1423          * in a change_notify msg.  Remember that a PCN message
1424          * includes the handle returned for the srv_spoolss_replyopenprinter()
1425          * call.  Therefore messages are grouped according to printer handle.
1426          */
1427
1428         for ( i=0; i<msg_count; i++ ) {
1429                 struct timeval msg_tv;
1430
1431                 if (msg_ptr + 4 - buf > data->length) {
1432                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1433                         return;
1434                 }
1435
1436                 msg_len = IVAL(msg_ptr,0);
1437                 msg_ptr += 4;
1438
1439                 if (msg_ptr + msg_len - buf > data->length) {
1440                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1441                         return;
1442                 }
1443
1444                 /* unpack messages */
1445
1446                 ZERO_STRUCT( notify );
1447                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1448                 msg_ptr += msg_len;
1449
1450                 /* add to correct list in container */
1451
1452                 notify_msg_ctr_addmsg( &messages, &notify );
1453
1454                 /* free memory that might have been allocated by notify2_unpack_msg() */
1455
1456                 if ( notify.len != 0 )
1457                         SAFE_FREE( notify.notify.data );
1458         }
1459
1460         /* process each group of messages */
1461
1462         num_groups = notify_msg_ctr_numgroups( &messages );
1463         for ( i=0; i<num_groups; i++ )
1464                 send_notify2_changes( &messages, i );
1465
1466
1467         /* cleanup */
1468
1469         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1470                 (uint32_t)msg_count ));
1471
1472         notify_msg_ctr_destroy( &messages );
1473
1474         return;
1475 }
1476
1477 /********************************************************************
1478  Send a message to ourself about new driver being installed
1479  so we can upgrade the information for each printer bound to this
1480  driver
1481  ********************************************************************/
1482
1483 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1484                                             struct messaging_context *msg_ctx)
1485 {
1486         int len = strlen(drivername);
1487
1488         if (!len)
1489                 return false;
1490
1491         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1492                 drivername));
1493
1494         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1495                            MSG_PRINTER_DRVUPGRADE,
1496                            (uint8_t *)drivername, len+1);
1497
1498         return true;
1499 }
1500
1501 void srv_spoolss_cleanup(void)
1502 {
1503         struct printer_session_counter *session_counter;
1504
1505         for (session_counter = counter_list;
1506              session_counter != NULL;
1507              session_counter = counter_list) {
1508                 DLIST_REMOVE(counter_list, session_counter);
1509                 TALLOC_FREE(session_counter);
1510         }
1511 }
1512
1513 /**********************************************************************
1514  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1515  over all printers, upgrading ones as necessary
1516  **********************************************************************/
1517
1518 void do_drv_upgrade_printer(struct messaging_context *msg,
1519                             void *private_data,
1520                             uint32_t msg_type,
1521                             struct server_id server_id,
1522                             DATA_BLOB *data)
1523 {
1524         TALLOC_CTX *tmp_ctx;
1525         struct auth_serversupplied_info *session_info = NULL;
1526         struct spoolss_PrinterInfo2 *pinfo2;
1527         NTSTATUS status;
1528         WERROR result;
1529         const char *drivername;
1530         int snum;
1531         int n_services = lp_numservices();
1532
1533         tmp_ctx = talloc_new(NULL);
1534         if (!tmp_ctx) return;
1535
1536         status = make_session_info_system(tmp_ctx, &session_info);
1537         if (!NT_STATUS_IS_OK(status)) {
1538                 DEBUG(0, ("do_drv_upgrade_printer: "
1539                           "Could not create system session_info\n"));
1540                 goto done;
1541         }
1542
1543         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1544         if (!drivername) {
1545                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1546                 goto done;
1547         }
1548
1549         DEBUG(10, ("do_drv_upgrade_printer: "
1550                    "Got message for new driver [%s]\n", drivername));
1551
1552         /* Iterate the printer list */
1553
1554         for (snum = 0; snum < n_services; snum++) {
1555                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1556                         continue;
1557                 }
1558
1559                 /* ignore [printers] share */
1560                 if (strequal(lp_const_servicename(snum), "printers")) {
1561                         continue;
1562                 }
1563
1564                 result = winreg_get_printer(tmp_ctx, session_info, msg,
1565                                             lp_const_servicename(snum),
1566                                             &pinfo2);
1567
1568                 if (!W_ERROR_IS_OK(result)) {
1569                         continue;
1570                 }
1571
1572                 if (!pinfo2->drivername) {
1573                         continue;
1574                 }
1575
1576                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1577                         continue;
1578                 }
1579
1580                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1581
1582                 /* all we care about currently is the change_id */
1583                 result = winreg_printer_update_changeid(tmp_ctx,
1584                                                         session_info,
1585                                                         msg,
1586                                                         pinfo2->printername);
1587
1588                 if (!W_ERROR_IS_OK(result)) {
1589                         DEBUG(3, ("do_drv_upgrade_printer: "
1590                                   "Failed to update changeid [%s]\n",
1591                                   win_errstr(result)));
1592                 }
1593         }
1594
1595         /* all done */
1596 done:
1597         talloc_free(tmp_ctx);
1598 }
1599
1600 /********************************************************************
1601  Update the cache for all printq's with a registered client
1602  connection
1603  ********************************************************************/
1604
1605 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1606 {
1607         struct printer_handle *printer = printers_list;
1608         int snum;
1609
1610         /* loop through all printers and update the cache where
1611            a client is connected */
1612         while (printer) {
1613                 if ((printer->printer_type == SPLHND_PRINTER) &&
1614                     ((printer->notify.cli_chan != NULL) &&
1615                      (printer->notify.cli_chan->active_connections > 0))) {
1616                         snum = print_queue_snum(printer->sharename);
1617                         print_queue_status(msg_ctx, snum, NULL, NULL);
1618                 }
1619
1620                 printer = printer->next;
1621         }
1622
1623         return;
1624 }
1625
1626 /****************************************************************
1627  _spoolss_OpenPrinter
1628 ****************************************************************/
1629
1630 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1631                             struct spoolss_OpenPrinter *r)
1632 {
1633         struct spoolss_OpenPrinterEx e;
1634         WERROR werr;
1635
1636         ZERO_STRUCT(e.in.userlevel);
1637
1638         e.in.printername        = r->in.printername;
1639         e.in.datatype           = r->in.datatype;
1640         e.in.devmode_ctr        = r->in.devmode_ctr;
1641         e.in.access_mask        = r->in.access_mask;
1642         e.in.level              = 0;
1643
1644         e.out.handle            = r->out.handle;
1645
1646         werr = _spoolss_OpenPrinterEx(p, &e);
1647
1648         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1649                 /* OpenPrinterEx returns this for a bad
1650                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1651                  * instead.
1652                  */
1653                 werr = WERR_INVALID_PRINTER_NAME;
1654         }
1655
1656         return werr;
1657 }
1658
1659 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1660                               struct spoolss_DeviceMode *orig,
1661                               struct spoolss_DeviceMode **dest)
1662 {
1663         struct spoolss_DeviceMode *dm;
1664
1665         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1666         if (!dm) {
1667                 return WERR_NOMEM;
1668         }
1669
1670         /* copy all values, then duplicate strings and structs */
1671         *dm = *orig;
1672
1673         dm->devicename = talloc_strdup(dm, orig->devicename);
1674         if (!dm->devicename) {
1675                 return WERR_NOMEM;
1676         }
1677         dm->formname = talloc_strdup(dm, orig->formname);
1678         if (!dm->formname) {
1679                 return WERR_NOMEM;
1680         }
1681         if (orig->driverextra_data.data) {
1682                 dm->driverextra_data.data =
1683                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1684                                         orig->driverextra_data.length);
1685                 if (!dm->driverextra_data.data) {
1686                         return WERR_NOMEM;
1687                 }
1688         }
1689
1690         *dest = dm;
1691         return WERR_OK;
1692 }
1693
1694 /****************************************************************
1695  _spoolss_OpenPrinterEx
1696 ****************************************************************/
1697
1698 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1699                               struct spoolss_OpenPrinterEx *r)
1700 {
1701         int snum;
1702         struct printer_handle *Printer=NULL;
1703         WERROR result;
1704
1705         if (!r->in.printername) {
1706                 return WERR_INVALID_PARAM;
1707         }
1708
1709         if (r->in.level < 0 || r->in.level > 3) {
1710                 return WERR_INVALID_PARAM;
1711         }
1712         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1713             (r->in.level == 2 && !r->in.userlevel.level2) ||
1714             (r->in.level == 3 && !r->in.userlevel.level3)) {
1715                 return WERR_INVALID_PARAM;
1716         }
1717
1718         /* some sanity check because you can open a printer or a print server */
1719         /* aka: \\server\printer or \\server */
1720
1721         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1722
1723         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1724         if (!W_ERROR_IS_OK(result)) {
1725                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1726                         "for printer %s\n", r->in.printername));
1727                 ZERO_STRUCTP(r->out.handle);
1728                 return result;
1729         }
1730
1731         Printer = find_printer_index_by_hnd(p, r->out.handle);
1732         if ( !Printer ) {
1733                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1734                         "handle we created for printer %s\n", r->in.printername));
1735                 close_printer_handle(p, r->out.handle);
1736                 ZERO_STRUCTP(r->out.handle);
1737                 return WERR_INVALID_PARAM;
1738         }
1739
1740         /*
1741          * First case: the user is opening the print server:
1742          *
1743          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1744          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1745          *
1746          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1747          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1748          * or if the user is listed in the smb.conf printer admin parameter.
1749          *
1750          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1751          * client view printer folder, but does not show the MSAPW.
1752          *
1753          * Note: this test needs code to check access rights here too. Jeremy
1754          * could you look at this?
1755          *
1756          * Second case: the user is opening a printer:
1757          * NT doesn't let us connect to a printer if the connecting user
1758          * doesn't have print permission.
1759          *
1760          * Third case: user is opening a Port Monitor
1761          * access checks same as opening a handle to the print server.
1762          */
1763
1764         switch (Printer->printer_type )
1765         {
1766         case SPLHND_SERVER:
1767         case SPLHND_PORTMON_TCP:
1768         case SPLHND_PORTMON_LOCAL:
1769                 /* Printserver handles use global struct... */
1770
1771                 snum = -1;
1772
1773                 /* Map standard access rights to object specific access rights */
1774
1775                 se_map_standard(&r->in.access_mask,
1776                                 &printserver_std_mapping);
1777
1778                 /* Deny any object specific bits that don't apply to print
1779                    servers (i.e printer and job specific bits) */
1780
1781                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1782
1783                 if (r->in.access_mask &
1784                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1785                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1786                         close_printer_handle(p, r->out.handle);
1787                         ZERO_STRUCTP(r->out.handle);
1788                         return WERR_ACCESS_DENIED;
1789                 }
1790
1791                 /* Allow admin access */
1792
1793                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1794                 {
1795                         if (!lp_ms_add_printer_wizard()) {
1796                                 close_printer_handle(p, r->out.handle);
1797                                 ZERO_STRUCTP(r->out.handle);
1798                                 return WERR_ACCESS_DENIED;
1799                         }
1800
1801                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1802                            and not a printer admin, then fail */
1803
1804                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1805                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1806                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1807                             !token_contains_name_in_list(
1808                                     uidtoname(p->session_info->utok.uid),
1809                                     p->session_info->info3->base.domain.string,
1810                                     NULL,
1811                                     p->session_info->security_token,
1812                                     lp_printer_admin(snum))) {
1813                                 close_printer_handle(p, r->out.handle);
1814                                 ZERO_STRUCTP(r->out.handle);
1815                                 DEBUG(3,("access DENIED as user is not root, "
1816                                         "has no printoperator privilege, "
1817                                         "not a member of the printoperator builtin group and "
1818                                         "is not in printer admin list"));
1819                                 return WERR_ACCESS_DENIED;
1820                         }
1821
1822                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1823                 }
1824                 else
1825                 {
1826                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1827                 }
1828
1829                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1830                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1831
1832                 /* We fall through to return WERR_OK */
1833                 break;
1834
1835         case SPLHND_PRINTER:
1836                 /* NT doesn't let us connect to a printer if the connecting user
1837                    doesn't have print permission.  */
1838
1839                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1840                         close_printer_handle(p, r->out.handle);
1841                         ZERO_STRUCTP(r->out.handle);
1842                         return WERR_BADFID;
1843                 }
1844
1845                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1846                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1847                 }
1848
1849                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1850
1851                 /* map an empty access mask to the minimum access mask */
1852                 if (r->in.access_mask == 0x0)
1853                         r->in.access_mask = PRINTER_ACCESS_USE;
1854
1855                 /*
1856                  * If we are not serving the printer driver for this printer,
1857                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1858                  * will keep NT clients happy  --jerry
1859                  */
1860
1861                 if (lp_use_client_driver(snum)
1862                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1863                 {
1864                         r->in.access_mask = PRINTER_ACCESS_USE;
1865                 }
1866
1867                 /* check smb.conf parameters and the the sec_desc */
1868
1869                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1870                                   p->client_id->name, p->client_id->addr)) {
1871                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1872                         ZERO_STRUCTP(r->out.handle);
1873                         return WERR_ACCESS_DENIED;
1874                 }
1875
1876                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1877                                    p->session_info->security_token, snum) ||
1878                     !print_access_check(p->session_info,
1879                                         p->msg_ctx,
1880                                         snum,
1881                                         r->in.access_mask)) {
1882                         DEBUG(3, ("access DENIED for printer open\n"));
1883                         close_printer_handle(p, r->out.handle);
1884                         ZERO_STRUCTP(r->out.handle);
1885                         return WERR_ACCESS_DENIED;
1886                 }
1887
1888                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1889                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1890                         close_printer_handle(p, r->out.handle);
1891                         ZERO_STRUCTP(r->out.handle);
1892                         return WERR_ACCESS_DENIED;
1893                 }
1894
1895                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1896                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1897                 else
1898                         r->in.access_mask = PRINTER_ACCESS_USE;
1899
1900                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1901                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1902
1903                 winreg_create_printer(p->mem_ctx,
1904                                       get_session_info_system(),
1905                                       p->msg_ctx,
1906                                       lp_const_servicename(snum));
1907
1908                 break;
1909
1910         default:
1911                 /* sanity check to prevent programmer error */
1912                 ZERO_STRUCTP(r->out.handle);
1913                 return WERR_BADFID;
1914         }
1915
1916         Printer->access_granted = r->in.access_mask;
1917
1918         /*
1919          * If the client sent a devmode in the OpenPrinter() call, then
1920          * save it here in case we get a job submission on this handle
1921          */
1922
1923          if ((Printer->printer_type != SPLHND_SERVER) &&
1924              r->in.devmode_ctr.devmode) {
1925                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1926                                 &Printer->devmode);
1927          }
1928
1929 #if 0   /* JERRY -- I'm doubtful this is really effective */
1930         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1931            optimization in Windows 2000 clients  --jerry */
1932
1933         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1934                 && (RA_WIN2K == get_remote_arch()) )
1935         {
1936                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1937                 sys_usleep( 500000 );
1938         }
1939 #endif
1940
1941         return WERR_OK;
1942 }
1943
1944 /****************************************************************
1945  _spoolss_ClosePrinter
1946 ****************************************************************/
1947
1948 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1949                              struct spoolss_ClosePrinter *r)
1950 {
1951         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1952
1953         if (Printer && Printer->document_started) {
1954                 struct spoolss_EndDocPrinter e;
1955
1956                 e.in.handle = r->in.handle;
1957
1958                 _spoolss_EndDocPrinter(p, &e);
1959         }
1960
1961         if (!close_printer_handle(p, r->in.handle))
1962                 return WERR_BADFID;
1963
1964         /* clear the returned printer handle.  Observed behavior
1965            from Win2k server.  Don't think this really matters.
1966            Previous code just copied the value of the closed
1967            handle.    --jerry */
1968
1969         ZERO_STRUCTP(r->out.handle);
1970
1971         return WERR_OK;
1972 }
1973
1974 /****************************************************************
1975  _spoolss_DeletePrinter
1976 ****************************************************************/
1977
1978 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1979                               struct spoolss_DeletePrinter *r)
1980 {
1981         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1982         WERROR result;
1983         int snum;
1984
1985         if (Printer && Printer->document_started) {
1986                 struct spoolss_EndDocPrinter e;
1987
1988                 e.in.handle = r->in.handle;
1989
1990                 _spoolss_EndDocPrinter(p, &e);
1991         }
1992
1993         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1994                 winreg_delete_printer_key(p->mem_ctx,
1995                                           get_session_info_system(),
1996                                           p->msg_ctx,
1997                                           lp_const_servicename(snum),
1998                                           "");
1999         }
2000
2001         result = delete_printer_handle(p, r->in.handle);
2002
2003         return result;
2004 }
2005
2006 /*******************************************************************
2007  * static function to lookup the version id corresponding to an
2008  * long architecture string
2009  ******************************************************************/
2010
2011 static const struct print_architecture_table_node archi_table[]= {
2012
2013         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2014         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2015         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2016         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2017         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2018         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2019         {"Windows x64",          SPL_ARCH_X64,          3 },
2020         {NULL,                   "",            -1 }
2021 };
2022
2023 static int get_version_id(const char *arch)
2024 {
2025         int i;
2026
2027         for (i=0; archi_table[i].long_archi != NULL; i++)
2028         {
2029                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2030                         return (archi_table[i].version);
2031         }
2032
2033         return -1;
2034 }
2035
2036 /****************************************************************
2037  _spoolss_DeletePrinterDriver
2038 ****************************************************************/
2039
2040 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2041                                     struct spoolss_DeletePrinterDriver *r)
2042 {
2043
2044         struct spoolss_DriverInfo8 *info = NULL;
2045         struct spoolss_DriverInfo8 *info_win2k = NULL;
2046         int                             version;
2047         WERROR                          status;
2048
2049         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2050            and not a printer admin, then fail */
2051
2052         if ( (p->session_info->utok.uid != sec_initial_uid())
2053              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2054                 && !token_contains_name_in_list(
2055                         uidtoname(p->session_info->utok.uid),
2056                         p->session_info->info3->base.domain.string,
2057                         NULL,
2058                         p->session_info->security_token,
2059                         lp_printer_admin(-1)) )
2060         {
2061                 return WERR_ACCESS_DENIED;
2062         }
2063
2064         /* check that we have a valid driver name first */
2065
2066         if ((version = get_version_id(r->in.architecture)) == -1)
2067                 return WERR_INVALID_ENVIRONMENT;
2068
2069         status = winreg_get_driver(p->mem_ctx,
2070                                    get_session_info_system(),
2071                                    p->msg_ctx,
2072                                    r->in.architecture, r->in.driver,
2073                                    version, &info);
2074         if (!W_ERROR_IS_OK(status)) {
2075                 /* try for Win2k driver if "Windows NT x86" */
2076
2077                 if ( version == 2 ) {
2078                         version = 3;
2079
2080                         status = winreg_get_driver(p->mem_ctx,
2081                                                    get_session_info_system(),
2082                                                    p->msg_ctx,
2083                                                    r->in.architecture,
2084                                                    r->in.driver,
2085                                                    version, &info);
2086                         if (!W_ERROR_IS_OK(status)) {
2087                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2088                                 goto done;
2089                         }
2090                 }
2091                 /* otherwise it was a failure */
2092                 else {
2093                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2094                         goto done;
2095                 }
2096
2097         }
2098
2099         if (printer_driver_in_use(p->mem_ctx,
2100                                   get_session_info_system(),
2101                                   p->msg_ctx,
2102                                   info)) {
2103                 status = WERR_PRINTER_DRIVER_IN_USE;
2104                 goto done;
2105         }
2106
2107         if (version == 2) {
2108                 status = winreg_get_driver(p->mem_ctx,
2109                                            get_session_info_system(),
2110                                            p->msg_ctx,
2111                                            r->in.architecture,
2112                                            r->in.driver, 3, &info_win2k);
2113                 if (W_ERROR_IS_OK(status)) {
2114                         /* if we get to here, we now have 2 driver info structures to remove */
2115                         /* remove the Win2k driver first*/
2116
2117                         status = winreg_del_driver(p->mem_ctx,
2118                                                    get_session_info_system(),
2119                                                    p->msg_ctx,
2120                                                    info_win2k, 3);
2121                         talloc_free(info_win2k);
2122
2123                         /* this should not have failed---if it did, report to client */
2124                         if (!W_ERROR_IS_OK(status)) {
2125                                 goto done;
2126                         }
2127                 }
2128         }
2129
2130         status = winreg_del_driver(p->mem_ctx,
2131                                    get_session_info_system(),
2132                                    p->msg_ctx,
2133                                    info, version);
2134
2135 done:
2136         talloc_free(info);
2137
2138         return status;
2139 }
2140
2141 /****************************************************************
2142  _spoolss_DeletePrinterDriverEx
2143 ****************************************************************/
2144
2145 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2146                                       struct spoolss_DeletePrinterDriverEx *r)
2147 {
2148         struct spoolss_DriverInfo8      *info = NULL;
2149         struct spoolss_DriverInfo8      *info_win2k = NULL;
2150         int                             version;
2151         bool                            delete_files;
2152         WERROR                          status;
2153
2154         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2155            and not a printer admin, then fail */
2156
2157         if ( (p->session_info->utok.uid != sec_initial_uid())
2158                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2159                 && !token_contains_name_in_list(
2160                         uidtoname(p->session_info->utok.uid),
2161                         p->session_info->info3->base.domain.string,
2162                         NULL,
2163                         p->session_info->security_token, lp_printer_admin(-1)) )
2164         {
2165                 return WERR_ACCESS_DENIED;
2166         }
2167
2168         /* check that we have a valid driver name first */
2169         if ((version = get_version_id(r->in.architecture)) == -1) {
2170                 /* this is what NT returns */
2171                 return WERR_INVALID_ENVIRONMENT;
2172         }
2173
2174         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2175                 version = r->in.version;
2176
2177         status = winreg_get_driver(p->mem_ctx,
2178                                    get_session_info_system(),
2179                                    p->msg_ctx,
2180                                    r->in.architecture,
2181                                    r->in.driver,
2182                                    version,
2183                                    &info);
2184         if (!W_ERROR_IS_OK(status)) {
2185                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2186
2187                 /*
2188                  * if the client asked for a specific version,
2189                  * or this is something other than Windows NT x86,
2190                  * then we've failed
2191                  */
2192
2193                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2194                         goto done;
2195
2196                 /* try for Win2k driver if "Windows NT x86" */
2197
2198                 version = 3;
2199                 status = winreg_get_driver(info,
2200                                            get_session_info_system(),
2201                                            p->msg_ctx,
2202                                            r->in.architecture,
2203                                            r->in.driver,
2204                                            version, &info);
2205                 if (!W_ERROR_IS_OK(status)) {
2206                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2207                         goto done;
2208                 }
2209         }
2210
2211         if (printer_driver_in_use(info,
2212                                   get_session_info_system(),
2213                                   p->msg_ctx,
2214                                   info)) {
2215                 status = WERR_PRINTER_DRIVER_IN_USE;
2216                 goto done;
2217         }
2218
2219         /*
2220          * we have a couple of cases to consider.
2221          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2222          *     then the delete should fail if **any** files overlap with
2223          *     other drivers
2224          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2225          *     non-overlapping files
2226          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2227          *     is set, the do not delete any files
2228          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2229          */
2230
2231         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2232
2233         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2234
2235         if (delete_files &&
2236             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2237             printer_driver_files_in_use(info,
2238                                         get_session_info_system(),
2239                                         p->msg_ctx,
2240                                         info)) {
2241                 /* no idea of the correct error here */
2242                 status = WERR_ACCESS_DENIED;
2243                 goto done;
2244         }
2245
2246
2247         /* also check for W32X86/3 if necessary; maybe we already have? */
2248
2249         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2250                 status = winreg_get_driver(info,
2251                                            get_session_info_system(),
2252                                            p->msg_ctx,
2253                                            r->in.architecture,
2254                                            r->in.driver, 3, &info_win2k);
2255                 if (W_ERROR_IS_OK(status)) {
2256
2257                         if (delete_files &&
2258                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2259                             printer_driver_files_in_use(info,
2260                                                         get_session_info_system(),
2261                                                         p->msg_ctx,
2262                                                         info_win2k)) {
2263                                 /* no idea of the correct error here */
2264                                 talloc_free(info_win2k);
2265                                 status = WERR_ACCESS_DENIED;
2266                                 goto done;
2267                         }
2268
2269                         /* if we get to here, we now have 2 driver info structures to remove */
2270                         /* remove the Win2k driver first*/
2271
2272                         status = winreg_del_driver(info,
2273                                                    get_session_info_system(),
2274                                                    p->msg_ctx,
2275                                                    info_win2k,
2276                                                    3);
2277
2278                         /* this should not have failed---if it did, report to client */
2279
2280                         if (!W_ERROR_IS_OK(status)) {
2281                                 goto done;
2282                         }
2283
2284                         /*
2285                          * now delete any associated files if delete_files is
2286                          * true. Even if this part failes, we return succes
2287                          * because the driver doesn not exist any more
2288                          */
2289                         if (delete_files) {
2290                                 delete_driver_files(get_session_info_system(),
2291                                                     info_win2k);
2292                         }
2293                 }
2294         }
2295
2296         status = winreg_del_driver(info,
2297                                    get_session_info_system(),
2298                                    p->msg_ctx,
2299                                    info,
2300                                    version);
2301         if (!W_ERROR_IS_OK(status)) {
2302                 goto done;
2303         }
2304
2305         /*
2306          * now delete any associated files if delete_files is
2307          * true. Even if this part failes, we return succes
2308          * because the driver doesn not exist any more
2309          */
2310         if (delete_files) {
2311                 delete_driver_files(get_session_info_system(), info);
2312         }
2313
2314 done:
2315         talloc_free(info);
2316         return status;
2317 }
2318
2319
2320 /********************************************************************
2321  GetPrinterData on a printer server Handle.
2322 ********************************************************************/
2323
2324 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2325                                             const char *value,
2326                                             enum winreg_Type *type,
2327                                             union spoolss_PrinterData *data)
2328 {
2329         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2330
2331         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2332                 *type = REG_DWORD;
2333                 data->value = 0x00;
2334                 return WERR_OK;
2335         }
2336
2337         if (!StrCaseCmp(value, "BeepEnabled")) {
2338                 *type = REG_DWORD;
2339                 data->value = 0x00;
2340                 return WERR_OK;
2341         }
2342
2343         if (!StrCaseCmp(value, "EventLog")) {
2344                 *type = REG_DWORD;
2345                 /* formally was 0x1b */
2346                 data->value = 0x00;
2347                 return WERR_OK;
2348         }
2349
2350         if (!StrCaseCmp(value, "NetPopup")) {
2351                 *type = REG_DWORD;
2352                 data->value = 0x00;
2353                 return WERR_OK;
2354         }
2355
2356         if (!StrCaseCmp(value, "MajorVersion")) {
2357                 *type = REG_DWORD;
2358
2359                 /* Windows NT 4.0 seems to not allow uploading of drivers
2360                    to a server that reports 0x3 as the MajorVersion.
2361                    need to investigate more how Win2k gets around this .
2362                    -- jerry */
2363
2364                 if (RA_WINNT == get_remote_arch()) {
2365                         data->value = 0x02;
2366                 } else {
2367                         data->value = 0x03;
2368                 }
2369
2370                 return WERR_OK;
2371         }
2372
2373         if (!StrCaseCmp(value, "MinorVersion")) {
2374                 *type = REG_DWORD;
2375                 data->value = 0x00;
2376                 return WERR_OK;
2377         }
2378
2379         /* REG_BINARY
2380          *  uint32_t size        = 0x114
2381          *  uint32_t major       = 5
2382          *  uint32_t minor       = [0|1]
2383          *  uint32_t build       = [2195|2600]
2384          *  extra unicode string = e.g. "Service Pack 3"
2385          */
2386         if (!StrCaseCmp(value, "OSVersion")) {
2387                 DATA_BLOB blob;
2388                 enum ndr_err_code ndr_err;
2389                 struct spoolss_OSVersion os;
2390
2391                 os.major                = 5;    /* Windows 2000 == 5.0 */
2392                 os.minor                = 0;
2393                 os.build                = 2195; /* build */
2394                 os.extra_string         = "";   /* leave extra string empty */
2395
2396                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2397                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2398                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2399                         return WERR_GENERAL_FAILURE;
2400                 }
2401
2402                 *type = REG_BINARY;
2403                 data->binary = blob;
2404
2405                 return WERR_OK;
2406         }
2407
2408
2409         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2410                 *type = REG_SZ;
2411
2412                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2413                 W_ERROR_HAVE_NO_MEMORY(data->string);
2414
2415                 return WERR_OK;
2416         }
2417
2418         if (!StrCaseCmp(value, "Architecture")) {
2419                 *type = REG_SZ;
2420                 data->string = talloc_strdup(mem_ctx,
2421                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2422                 W_ERROR_HAVE_NO_MEMORY(data->string);
2423
2424                 return WERR_OK;
2425         }
2426
2427         if (!StrCaseCmp(value, "DsPresent")) {
2428                 *type = REG_DWORD;
2429
2430                 /* only show the publish check box if we are a
2431                    member of a AD domain */
2432
2433                 if (lp_security() == SEC_ADS) {
2434                         data->value = 0x01;
2435                 } else {
2436                         data->value = 0x00;
2437                 }
2438                 return WERR_OK;
2439         }
2440
2441         if (!StrCaseCmp(value, "DNSMachineName")) {
2442                 const char *hostname = get_mydnsfullname();
2443
2444                 if (!hostname) {
2445                         return WERR_BADFILE;
2446                 }
2447
2448                 *type = REG_SZ;
2449                 data->string = talloc_strdup(mem_ctx, hostname);
2450                 W_ERROR_HAVE_NO_MEMORY(data->string);
2451
2452                 return WERR_OK;
2453         }
2454
2455         *type = REG_NONE;
2456
2457         return WERR_INVALID_PARAM;
2458 }
2459
2460 /****************************************************************
2461  _spoolss_GetPrinterData
2462 ****************************************************************/
2463
2464 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2465                                struct spoolss_GetPrinterData *r)
2466 {
2467         struct spoolss_GetPrinterDataEx r2;
2468
2469         r2.in.handle            = r->in.handle;
2470         r2.in.key_name          = "PrinterDriverData";
2471         r2.in.value_name        = r->in.value_name;
2472         r2.in.offered           = r->in.offered;
2473         r2.out.type             = r->out.type;
2474         r2.out.data             = r->out.data;
2475         r2.out.needed           = r->out.needed;
2476
2477         return _spoolss_GetPrinterDataEx(p, &r2);
2478 }
2479
2480 /*********************************************************
2481  Connect to the client machine.
2482 **********************************************************/
2483
2484 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2485                         struct sockaddr_storage *client_ss, const char *remote_machine)
2486 {
2487         NTSTATUS ret;
2488         struct cli_state *the_cli;
2489         struct sockaddr_storage rm_addr;
2490         char addr[INET6_ADDRSTRLEN];
2491
2492         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2493                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2494                         remote_machine));
2495                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2496                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2497                         return false;
2498                 }
2499                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2500         } else {
2501                 rm_addr = *client_ss;
2502                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2503                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2504                         addr));
2505         }
2506
2507         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2508                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2509                         addr));
2510                 return false;
2511         }
2512
2513         /* setup the connection */
2514         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2515                 &rm_addr, 0, "IPC$", "IPC",
2516                 "", /* username */
2517                 "", /* domain */
2518                 "", /* password */
2519                 0, lp_client_signing());
2520
2521         if ( !NT_STATUS_IS_OK( ret ) ) {
2522                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2523                         remote_machine ));
2524                 return false;
2525         }
2526
2527         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2528                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2529                 cli_shutdown(the_cli);
2530                 return false;
2531         }
2532
2533         /*
2534          * Ok - we have an anonymous connection to the IPC$ share.
2535          * Now start the NT Domain stuff :-).
2536          */
2537
2538         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2539         if (!NT_STATUS_IS_OK(ret)) {
2540                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2541                         remote_machine, nt_errstr(ret)));
2542                 cli_shutdown(the_cli);
2543                 return false;
2544         }
2545
2546         return true;
2547 }
2548
2549 /***************************************************************************
2550  Connect to the client.
2551 ****************************************************************************/
2552
2553 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2554                                         uint32_t localprinter,
2555                                         enum winreg_Type type,
2556                                         struct policy_handle *handle,
2557                                         struct notify_back_channel **_chan,
2558                                         struct sockaddr_storage *client_ss,
2559                                         struct messaging_context *msg_ctx)
2560 {
2561         WERROR result;
2562         NTSTATUS status;
2563         struct notify_back_channel *chan;
2564
2565         for (chan = back_channels; chan; chan = chan->next) {
2566                 if (memcmp(&chan->client_address, client_ss,
2567                            sizeof(struct sockaddr_storage)) == 0) {
2568                         break;
2569                 }
2570         }
2571
2572         /*
2573          * If it's the first connection, contact the client
2574          * and connect to the IPC$ share anonymously
2575          */
2576         if (!chan) {
2577                 fstring unix_printer;
2578
2579                 /* the +2 is to strip the leading 2 backslashs */
2580                 fstrcpy(unix_printer, printer + 2);
2581
2582                 chan = talloc_zero(back_channels, struct notify_back_channel);
2583                 if (!chan) {
2584                         return false;
2585                 }
2586                 chan->client_address = *client_ss;
2587
2588                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2589                         TALLOC_FREE(chan);
2590                         return false;
2591                 }
2592                 chan->binding_handle = chan->cli_pipe->binding_handle;
2593
2594                 DLIST_ADD(back_channels, chan);
2595
2596                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2597                                    receive_notify2_message_list);
2598                 /* Tell the connections db we're now interested in printer
2599                  * notify messages. */
2600                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2601                                             true, FLAG_MSG_PRINT_NOTIFY);
2602         }
2603
2604         /*
2605          * Tell the specific printing tdb we want messages for this printer
2606          * by registering our PID.
2607          */
2608
2609         if (!print_notify_register_pid(snum)) {
2610                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2611                           printer));
2612         }
2613
2614         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2615                                                  talloc_tos(),
2616                                                  printer,
2617                                                  localprinter,
2618                                                  type,
2619                                                  0,
2620                                                  NULL,
2621                                                  handle,
2622                                                  &result);
2623         if (!NT_STATUS_IS_OK(status)) {
2624                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2625                 result = ntstatus_to_werror(status);
2626         } else if (!W_ERROR_IS_OK(result)) {
2627                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2628         }
2629
2630         chan->active_connections++;
2631         *_chan = chan;
2632
2633         return (W_ERROR_IS_OK(result));
2634 }
2635
2636 /****************************************************************
2637  ****************************************************************/
2638
2639 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2640                                                              const struct spoolss_NotifyOption *r)
2641 {
2642         struct spoolss_NotifyOption *option;
2643         uint32_t i,k;
2644
2645         if (!r) {
2646                 return NULL;
2647         }
2648
2649         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2650         if (!option) {
2651                 return NULL;
2652         }
2653
2654         *option = *r;
2655
2656         if (!option->count) {
2657                 return option;
2658         }
2659
2660         option->types = talloc_zero_array(option,
2661                 struct spoolss_NotifyOptionType, option->count);
2662         if (!option->types) {
2663                 talloc_free(option);
2664                 return NULL;
2665         }
2666
2667         for (i=0; i < option->count; i++) {
2668                 option->types[i] = r->types[i];
2669
2670                 if (option->types[i].count) {
2671                         option->types[i].fields = talloc_zero_array(option,
2672                                 union spoolss_Field, option->types[i].count);
2673                         if (!option->types[i].fields) {
2674                                 talloc_free(option);
2675                                 return NULL;
2676                         }
2677                         for (k=0; k<option->types[i].count; k++) {
2678                                 option->types[i].fields[k] =
2679                                         r->types[i].fields[k];
2680                         }
2681                 }
2682         }
2683
2684         return option;
2685 }
2686
2687 /****************************************************************
2688  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2689  *
2690  * before replying OK: status=0 a rpc call is made to the workstation
2691  * asking ReplyOpenPrinter
2692  *
2693  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2694  * called from api_spoolss_rffpcnex
2695 ****************************************************************/
2696
2697 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2698                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2699 {
2700         int snum = -1;
2701         struct spoolss_NotifyOption *option = r->in.notify_options;
2702         struct sockaddr_storage client_ss;
2703
2704         /* store the notify value in the printer struct */
2705
2706         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2707
2708         if (!Printer) {
2709                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2710                         "Invalid handle (%s:%u:%u).\n",
2711                         OUR_HANDLE(r->in.handle)));
2712                 return WERR_BADFID;
2713         }
2714
2715         Printer->notify.flags           = r->in.flags;
2716         Printer->notify.options         = r->in.options;
2717         Printer->notify.printerlocal    = r->in.printer_local;
2718         Printer->notify.msg_ctx         = p->msg_ctx;
2719
2720         TALLOC_FREE(Printer->notify.option);
2721         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2722
2723         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2724
2725         /* Connect to the client machine and send a ReplyOpenPrinter */
2726
2727         if ( Printer->printer_type == SPLHND_SERVER)
2728                 snum = -1;
2729         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2730                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2731                 return WERR_BADFID;
2732
2733         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2734                 "client_address is %s\n", p->client_id->addr));
2735
2736         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2737                                    AI_NUMERICHOST)) {
2738                 return WERR_SERVER_UNAVAILABLE;
2739         }
2740
2741         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2742                                         Printer->notify.printerlocal, REG_SZ,
2743                                         &Printer->notify.cli_hnd,
2744                                         &Printer->notify.cli_chan,
2745                                         &client_ss, p->msg_ctx)) {
2746                 return WERR_SERVER_UNAVAILABLE;
2747         }
2748
2749         return WERR_OK;
2750 }
2751
2752 /*******************************************************************
2753  * fill a notify_info_data with the servername
2754  ********************************************************************/
2755
2756 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2757                                        int snum,
2758                                        struct spoolss_Notify *data,
2759                                        print_queue_struct *queue,
2760                                        struct spoolss_PrinterInfo2 *pinfo2,
2761                                        TALLOC_CTX *mem_ctx)
2762 {
2763         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2764 }
2765
2766 /*******************************************************************
2767  * fill a notify_info_data with the printername (not including the servername).
2768  ********************************************************************/
2769
2770 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2771                                         int snum,
2772                                         struct spoolss_Notify *data,
2773                                         print_queue_struct *queue,
2774                                         struct spoolss_PrinterInfo2 *pinfo2,
2775                                         TALLOC_CTX *mem_ctx)
2776 {
2777         /* the notify name should not contain the \\server\ part */
2778         const char *p = strrchr(pinfo2->printername, '\\');
2779
2780         if (!p) {
2781                 p = pinfo2->printername;
2782         } else {
2783                 p++;
2784         }
2785
2786         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2787 }
2788
2789 /*******************************************************************
2790  * fill a notify_info_data with the servicename
2791  ********************************************************************/
2792
2793 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2794                                       int snum,
2795                                       struct spoolss_Notify *data,
2796                                       print_queue_struct *queue,
2797                                       struct spoolss_PrinterInfo2 *pinfo2,
2798                                       TALLOC_CTX *mem_ctx)
2799 {
2800         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2801 }
2802
2803 /*******************************************************************
2804  * fill a notify_info_data with the port name
2805  ********************************************************************/
2806
2807 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2808                                      int snum,
2809                                      struct spoolss_Notify *data,
2810                                      print_queue_struct *queue,
2811                                      struct spoolss_PrinterInfo2 *pinfo2,
2812                                      TALLOC_CTX *mem_ctx)
2813 {
2814         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2815 }
2816
2817 /*******************************************************************
2818  * fill a notify_info_data with the printername
2819  * but it doesn't exist, have to see what to do
2820  ********************************************************************/
2821
2822 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2823                                        int snum,
2824                                        struct spoolss_Notify *data,
2825                                        print_queue_struct *queue,
2826                                        struct spoolss_PrinterInfo2 *pinfo2,
2827                                        TALLOC_CTX *mem_ctx)
2828 {
2829         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2830 }
2831
2832 /*******************************************************************
2833  * fill a notify_info_data with the comment
2834  ********************************************************************/
2835
2836 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2837                                    int snum,
2838                                    struct spoolss_Notify *data,
2839                                    print_queue_struct *queue,
2840                                    struct spoolss_PrinterInfo2 *pinfo2,
2841                                    TALLOC_CTX *mem_ctx)
2842 {
2843         const char *p;
2844
2845         if (*pinfo2->comment == '\0') {
2846                 p = lp_comment(snum);
2847         } else {
2848                 p = pinfo2->comment;
2849         }
2850
2851         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2852 }
2853
2854 /*******************************************************************
2855  * fill a notify_info_data with the comment
2856  * location = "Room 1, floor 2, building 3"
2857  ********************************************************************/
2858
2859 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2860                                     int snum,
2861                                     struct spoolss_Notify *data,
2862                                     print_queue_struct *queue,
2863                                     struct spoolss_PrinterInfo2 *pinfo2,
2864                                     TALLOC_CTX *mem_ctx)
2865 {
2866         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2867 }
2868
2869 /*******************************************************************
2870  * fill a notify_info_data with the device mode
2871  * jfm:xxxx don't to it for know but that's a real problem !!!
2872  ********************************************************************/
2873
2874 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2875                                    int snum,
2876                                    struct spoolss_Notify *data,
2877                                    print_queue_struct *queue,
2878                                    struct spoolss_PrinterInfo2 *pinfo2,
2879                                    TALLOC_CTX *mem_ctx)
2880 {
2881         /* for a dummy implementation we have to zero the fields */
2882         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2883 }
2884
2885 /*******************************************************************
2886  * fill a notify_info_data with the separator file name
2887  ********************************************************************/
2888
2889 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2890                                    int snum,
2891                                    struct spoolss_Notify *data,
2892                                    print_queue_struct *queue,
2893                                    struct spoolss_PrinterInfo2 *pinfo2,
2894                                    TALLOC_CTX *mem_ctx)
2895 {
2896         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2897 }
2898
2899 /*******************************************************************
2900  * fill a notify_info_data with the print processor
2901  * jfm:xxxx return always winprint to indicate we don't do anything to it
2902  ********************************************************************/
2903
2904 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2905                                            int snum,
2906                                            struct spoolss_Notify *data,
2907                                            print_queue_struct *queue,
2908                                            struct spoolss_PrinterInfo2 *pinfo2,
2909                                            TALLOC_CTX *mem_ctx)
2910 {
2911         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2912 }
2913
2914 /*******************************************************************
2915  * fill a notify_info_data with the print processor options
2916  * jfm:xxxx send an empty string
2917  ********************************************************************/
2918
2919 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2920                                       int snum,
2921                                       struct spoolss_Notify *data,
2922                                       print_queue_struct *queue,
2923                                       struct spoolss_PrinterInfo2 *pinfo2,
2924                                       TALLOC_CTX *mem_ctx)
2925 {
2926         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2927 }
2928
2929 /*******************************************************************
2930  * fill a notify_info_data with the data type
2931  * jfm:xxxx always send RAW as data type
2932  ********************************************************************/
2933
2934 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2935                                     int snum,
2936                                     struct spoolss_Notify *data,
2937                                     print_queue_struct *queue,
2938                                     struct spoolss_PrinterInfo2 *pinfo2,
2939                                     TALLOC_CTX *mem_ctx)
2940 {
2941         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2942 }
2943
2944 /*******************************************************************
2945  * fill a notify_info_data with the security descriptor
2946  * jfm:xxxx send an null pointer to say no security desc
2947  * have to implement security before !
2948  ********************************************************************/
2949
2950 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2951                                          int snum,
2952                                          struct spoolss_Notify *data,
2953                                          print_queue_struct *queue,
2954                                          struct spoolss_PrinterInfo2 *pinfo2,
2955                                          TALLOC_CTX *mem_ctx)
2956 {
2957         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2958 }
2959
2960 /*******************************************************************
2961  * fill a notify_info_data with the attributes
2962  * jfm:xxxx a samba printer is always shared
2963  ********************************************************************/
2964
2965 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2966                                       int snum,
2967                                       struct spoolss_Notify *data,
2968                                       print_queue_struct *queue,
2969                                       struct spoolss_PrinterInfo2 *pinfo2,
2970                                       TALLOC_CTX *mem_ctx)
2971 {
2972         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2973 }
2974
2975 /*******************************************************************
2976  * fill a notify_info_data with the priority
2977  ********************************************************************/
2978
2979 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2980                                     int snum,
2981                                     struct spoolss_Notify *data,
2982                                     print_queue_struct *queue,
2983                                     struct spoolss_PrinterInfo2 *pinfo2,
2984                                     TALLOC_CTX *mem_ctx)
2985 {
2986         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2987 }
2988
2989 /*******************************************************************
2990  * fill a notify_info_data with the default priority
2991  ********************************************************************/
2992
2993 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2994                                             int snum,
2995                                             struct spoolss_Notify *data,
2996                                             print_queue_struct *queue,
2997                                             struct spoolss_PrinterInfo2 *pinfo2,
2998                                             TALLOC_CTX *mem_ctx)
2999 {
3000         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3001 }
3002
3003 /*******************************************************************
3004  * fill a notify_info_data with the start time
3005  ********************************************************************/
3006
3007 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3008                                       int snum,
3009                                       struct spoolss_Notify *data,
3010                                       print_queue_struct *queue,
3011                                       struct spoolss_PrinterInfo2 *pinfo2,
3012                                       TALLOC_CTX *mem_ctx)
3013 {
3014         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3015 }
3016
3017 /*******************************************************************
3018  * fill a notify_info_data with the until time
3019  ********************************************************************/
3020
3021 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3022                                       int snum,
3023                                       struct spoolss_Notify *data,
3024                                       print_queue_struct *queue,
3025                                       struct spoolss_PrinterInfo2 *pinfo2,
3026                                       TALLOC_CTX *mem_ctx)
3027 {
3028         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3029 }
3030
3031 /*******************************************************************
3032  * fill a notify_info_data with the status
3033  ********************************************************************/
3034
3035 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3036                                   int snum,
3037                                   struct spoolss_Notify *data,
3038                                   print_queue_struct *queue,
3039                                   struct spoolss_PrinterInfo2 *pinfo2,
3040                                   TALLOC_CTX *mem_ctx)
3041 {
3042         print_status_struct status;
3043
3044         print_queue_length(msg_ctx, snum, &status);
3045         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3046 }
3047
3048 /*******************************************************************
3049  * fill a notify_info_data with the number of jobs queued
3050  ********************************************************************/
3051
3052 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3053                                  int snum,
3054                                  struct spoolss_Notify *data,
3055                                  print_queue_struct *queue,
3056                                  struct spoolss_PrinterInfo2 *pinfo2,
3057                                  TALLOC_CTX *mem_ctx)
3058 {
3059         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3060                 data, print_queue_length(msg_ctx, snum, NULL));
3061 }
3062
3063 /*******************************************************************
3064  * fill a notify_info_data with the average ppm
3065  ********************************************************************/
3066
3067 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3068                                        int snum,
3069                                        struct spoolss_Notify *data,
3070                                        print_queue_struct *queue,
3071                                        struct spoolss_PrinterInfo2 *pinfo2,
3072                                        TALLOC_CTX *mem_ctx)
3073 {
3074         /* always respond 8 pages per minutes */
3075         /* a little hard ! */
3076         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3077 }
3078
3079 /*******************************************************************
3080  * fill a notify_info_data with username
3081  ********************************************************************/
3082
3083 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3084                                     int snum,
3085                                     struct spoolss_Notify *data,
3086                                     print_queue_struct *queue,
3087                                     struct spoolss_PrinterInfo2 *pinfo2,
3088                                     TALLOC_CTX *mem_ctx)
3089 {
3090         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3091 }
3092
3093 /*******************************************************************
3094  * fill a notify_info_data with job status
3095  ********************************************************************/
3096
3097 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3098                                       int snum,
3099                                       struct spoolss_Notify *data,
3100                                       print_queue_struct *queue,
3101                                       struct spoolss_PrinterInfo2 *pinfo2,
3102                                       TALLOC_CTX *mem_ctx)
3103 {
3104         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3105 }
3106
3107 /*******************************************************************
3108  * fill a notify_info_data with job name
3109  ********************************************************************/
3110
3111 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3112                                     int snum,
3113                                     struct spoolss_Notify *data,
3114                                     print_queue_struct *queue,
3115                                     struct spoolss_PrinterInfo2 *pinfo2,
3116                                     TALLOC_CTX *mem_ctx)
3117 {
3118         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3119 }
3120
3121 /*******************************************************************
3122  * fill a notify_info_data with job status
3123  ********************************************************************/
3124
3125 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3126                                              int snum,
3127                                              struct spoolss_Notify *data,
3128                                              print_queue_struct *queue,
3129                                              struct spoolss_PrinterInfo2 *pinfo2,
3130                                              TALLOC_CTX *mem_ctx)
3131 {
3132         /*
3133          * Now we're returning job status codes we just return a "" here. JRA.
3134          */
3135
3136         const char *p = "";
3137
3138 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3139         p = "unknown";
3140
3141         switch (queue->status) {
3142         case LPQ_QUEUED:
3143                 p = "Queued";
3144                 break;
3145         case LPQ_PAUSED:
3146                 p = "";    /* NT provides the paused string */
3147                 break;
3148         case LPQ_SPOOLING:
3149                 p = "Spooling";
3150                 break;
3151         case LPQ_PRINTING:
3152                 p = "Printing";
3153                 break;
3154         }
3155 #endif /* NO LONGER NEEDED. */
3156
3157         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3158 }
3159
3160 /*******************************************************************
3161  * fill a notify_info_data with job time
3162  ********************************************************************/
3163
3164 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3165                                     int snum,
3166                                     struct spoolss_Notify *data,
3167                                     print_queue_struct *queue,
3168                                     struct spoolss_PrinterInfo2 *pinfo2,
3169                                     TALLOC_CTX *mem_ctx)
3170 {
3171         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3172 }
3173
3174 /*******************************************************************
3175  * fill a notify_info_data with job size
3176  ********************************************************************/
3177
3178 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3179                                     int snum,
3180                                     struct spoolss_Notify *data,
3181                                     print_queue_struct *queue,
3182                                     struct spoolss_PrinterInfo2 *pinfo2,
3183                                     TALLOC_CTX *mem_ctx)
3184 {
3185         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3186 }
3187
3188 /*******************************************************************
3189  * fill a notify_info_data with page info
3190  ********************************************************************/
3191 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3192                                        int snum,
3193                                 struct spoolss_Notify *data,
3194                                 print_queue_struct *queue,
3195                                 struct spoolss_PrinterInfo2 *pinfo2,
3196                                 TALLOC_CTX *mem_ctx)
3197 {
3198         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3199 }
3200
3201 /*******************************************************************
3202  * fill a notify_info_data with pages printed info.
3203  ********************************************************************/
3204 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3205                                          int snum,
3206                                 struct spoolss_Notify *data,
3207                                 print_queue_struct *queue,
3208                                 struct spoolss_PrinterInfo2 *pinfo2,
3209                                 TALLOC_CTX *mem_ctx)
3210 {
3211         /* Add code when back-end tracks this */
3212         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3213 }
3214
3215 /*******************************************************************
3216  Fill a notify_info_data with job position.
3217  ********************************************************************/
3218
3219 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3220                                         int snum,
3221                                         struct spoolss_Notify *data,
3222                                         print_queue_struct *queue,
3223                                         struct spoolss_PrinterInfo2 *pinfo2,
3224                                         TALLOC_CTX *mem_ctx)
3225 {
3226         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3227 }
3228
3229 /*******************************************************************
3230  Fill a notify_info_data with submitted time.
3231  ********************************************************************/
3232
3233 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3234                                           int snum,
3235                                           struct spoolss_Notify *data,
3236                                           print_queue_struct *queue,
3237                                           struct spoolss_PrinterInfo2 *pinfo2,
3238                                           TALLOC_CTX *mem_ctx)
3239 {
3240         data->data.string.string = NULL;
3241         data->data.string.size = 0;
3242
3243         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3244                                &data->data.string.string,
3245                                &data->data.string.size);
3246
3247 }
3248
3249 struct s_notify_info_data_table
3250 {
3251         enum spoolss_NotifyType type;
3252         uint16_t field;
3253         const char *name;
3254         enum spoolss_NotifyTable variable_type;
3255         void (*fn) (struct messaging_context *msg_ctx,
3256                     int snum, struct spoolss_Notify *data,
3257                     print_queue_struct *queue,
3258                     struct spoolss_PrinterInfo2 *pinfo2,
3259                     TALLOC_CTX *mem_ctx);
3260 };
3261
3262 /* A table describing the various print notification constants and
3263    whether the notification data is a pointer to a variable sized
3264    buffer, a one value uint32_t or a two value uint32_t. */
3265
3266 static const struct s_notify_info_data_table notify_info_data_table[] =
3267 {
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3305 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3306 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3316 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3317 };
3318
3319 /*******************************************************************
3320  Return the variable_type of info_data structure.
3321 ********************************************************************/
3322
3323 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3324                                                                   uint16_t field)
3325 {
3326         int i=0;
3327
3328         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3329                 if ( (notify_info_data_table[i].type == type) &&
3330                      (notify_info_data_table[i].field == field) ) {
3331                         return notify_info_data_table[i].variable_type;
3332                 }
3333         }
3334
3335         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3336
3337         return (enum spoolss_NotifyTable) 0;
3338 }
3339
3340 /****************************************************************************
3341 ****************************************************************************/
3342
3343 static bool search_notify(enum spoolss_NotifyType type,
3344                           uint16_t field,
3345                           int *value)
3346 {
3347         int i;
3348
3349         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3350                 if (notify_info_data_table[i].type == type &&
3351                     notify_info_data_table[i].field == field &&
3352                     notify_info_data_table[i].fn != NULL) {
3353                         *value = i;
3354                         return true;
3355                 }
3356         }
3357
3358         return false;
3359 }
3360
3361 /****************************************************************************
3362 ****************************************************************************/
3363
3364 static void construct_info_data(struct spoolss_Notify *info_data,
3365                                 enum spoolss_NotifyType type,
3366                                 uint16_t field, int id)
3367 {
3368         info_data->type                 = type;
3369         info_data->field.field          = field;
3370         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3371         info_data->job_id               = id;
3372 }
3373
3374 /*******************************************************************
3375  *
3376  * fill a notify_info struct with info asked
3377  *
3378  ********************************************************************/
3379
3380 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3381                                           struct printer_handle *print_hnd,
3382                                           struct spoolss_NotifyInfo *info,
3383                                           struct spoolss_PrinterInfo2 *pinfo2,
3384                                           int snum,
3385                                           const struct spoolss_NotifyOptionType *option_type,
3386                                           uint32_t id,
3387                                           TALLOC_CTX *mem_ctx)
3388 {
3389         int field_num,j;
3390         enum spoolss_NotifyType type;
3391         uint16_t field;
3392
3393         struct spoolss_Notify *current_data;
3394         print_queue_struct *queue=NULL;
3395
3396         type = option_type->type;
3397
3398         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3399                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3400                 option_type->count, lp_servicename(snum)));
3401
3402         for(field_num=0; field_num < option_type->count; field_num++) {
3403                 field = option_type->fields[field_num].field;
3404
3405                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3406
3407                 if (!search_notify(type, field, &j) )
3408                         continue;
3409
3410                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3411                                                       struct spoolss_Notify,
3412                                                       info->count + 1);
3413                 if (info->notifies == NULL) {
3414                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3415                         return false;
3416                 }
3417
3418                 current_data = &info->notifies[info->count];
3419
3420                 construct_info_data(current_data, type, field, id);
3421
3422                 DEBUG(10, ("construct_notify_printer_info: "
3423                            "calling [%s]  snum=%d  printername=[%s])\n",
3424                            notify_info_data_table[j].name, snum,
3425                            pinfo2->printername));
3426
3427                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3428                                              queue, pinfo2, mem_ctx);
3429
3430                 info->count++;
3431         }
3432
3433         return true;
3434 }
3435
3436 /*******************************************************************
3437  *
3438  * fill a notify_info struct with info asked
3439  *
3440  ********************************************************************/
3441
3442 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3443                                        print_queue_struct *queue,
3444                                        struct spoolss_NotifyInfo *info,
3445                                        struct spoolss_PrinterInfo2 *pinfo2,
3446                                        int snum,
3447                                        const struct spoolss_NotifyOptionType *option_type,
3448                                        uint32_t id,
3449                                        TALLOC_CTX *mem_ctx)
3450 {
3451         int field_num,j;
3452         enum spoolss_NotifyType type;
3453         uint16_t field;
3454         struct spoolss_Notify *current_data;
3455
3456         DEBUG(4,("construct_notify_jobs_info\n"));
3457
3458         type = option_type->type;
3459
3460         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3461                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3462                 option_type->count));
3463
3464         for(field_num=0; field_num<option_type->count; field_num++) {
3465                 field = option_type->fields[field_num].field;
3466
3467                 if (!search_notify(type, field, &j) )
3468                         continue;
3469
3470                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3471                                                       struct spoolss_Notify,
3472                                                       info->count + 1);
3473                 if (info->notifies == NULL) {
3474                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3475                         return false;
3476                 }
3477
3478                 current_data=&(info->notifies[info->count]);
3479
3480                 construct_info_data(current_data, type, field, id);
3481                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3482                                              queue, pinfo2, mem_ctx);
3483                 info->count++;
3484         }
3485
3486         return true;
3487 }
3488
3489 /*
3490  * JFM: The enumeration is not that simple, it's even non obvious.
3491  *
3492  * let's take an example: I want to monitor the PRINTER SERVER for
3493  * the printer's name and the number of jobs currently queued.
3494  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3495  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3496  *
3497  * I have 3 printers on the back of my server.
3498  *
3499  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3500  * structures.
3501  *   Number     Data                    Id
3502  *      1       printer 1 name          1
3503  *      2       printer 1 cjob          1
3504  *      3       printer 2 name          2
3505  *      4       printer 2 cjob          2
3506  *      5       printer 3 name          3
3507  *      6       printer 3 name          3
3508  *
3509  * that's the print server case, the printer case is even worse.
3510  */
3511
3512 /*******************************************************************
3513  *
3514  * enumerate all printers on the printserver
3515  * fill a notify_info struct with info asked
3516  *
3517  ********************************************************************/
3518
3519 static WERROR printserver_notify_info(struct pipes_struct *p,
3520                                       struct policy_handle *hnd,
3521                                       struct spoolss_NotifyInfo *info,
3522                                       TALLOC_CTX *mem_ctx)
3523 {
3524         int snum;
3525         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3526         int n_services=lp_numservices();
3527         int i;
3528         struct spoolss_NotifyOption *option;
3529         struct spoolss_NotifyOptionType option_type;
3530         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3531         WERROR result;
3532
3533         DEBUG(4,("printserver_notify_info\n"));
3534
3535         if (!Printer)
3536                 return WERR_BADFID;
3537
3538         option = Printer->notify.option;
3539
3540         info->version   = 2;
3541         info->notifies  = NULL;
3542         info->count     = 0;
3543
3544         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3545            sending a ffpcn() request first */
3546
3547         if ( !option )
3548                 return WERR_BADFID;
3549
3550         for (i=0; i<option->count; i++) {
3551                 option_type = option->types[i];
3552
3553                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3554                         continue;
3555
3556                 for (snum = 0; snum < n_services; snum++) {
3557                         if (!lp_browseable(snum) ||
3558                             !lp_snum_ok(snum) ||
3559                             !lp_print_ok(snum)) {
3560                                 continue; /* skip */
3561                         }
3562
3563                         /* Maybe we should use the SYSTEM session_info here... */
3564                         result = winreg_get_printer(mem_ctx,
3565                                                     get_session_info_system(),
3566                                                     p->msg_ctx,
3567                                                     lp_servicename(snum),
3568                                                     &pinfo2);
3569                         if (!W_ERROR_IS_OK(result)) {
3570                                 DEBUG(4, ("printserver_notify_info: "
3571                                           "Failed to get printer [%s]\n",
3572                                           lp_servicename(snum)));
3573                                 continue;
3574                         }
3575
3576
3577                         construct_notify_printer_info(p->msg_ctx,
3578                                                       Printer, info,
3579                                                       pinfo2, snum,
3580                                                       &option_type, snum,
3581                                                       mem_ctx);
3582
3583                         TALLOC_FREE(pinfo2);
3584                 }
3585         }
3586
3587 #if 0
3588         /*
3589          * Debugging information, don't delete.
3590          */
3591
3592         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3593         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3594         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3595
3596         for (i=0; i<info->count; i++) {
3597                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3598                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3599                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3600         }
3601 #endif
3602
3603         return WERR_OK;
3604 }
3605
3606 /*******************************************************************
3607  *
3608  * fill a notify_info struct with info asked
3609  *
3610  ********************************************************************/
3611
3612 static WERROR printer_notify_info(struct pipes_struct *p,
3613                                   struct policy_handle *hnd,
3614                                   struct spoolss_NotifyInfo *info,
3615                                   TALLOC_CTX *mem_ctx)
3616 {
3617         int snum;
3618         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3619         int i;
3620         uint32_t id;
3621         struct spoolss_NotifyOption *option;
3622         struct spoolss_NotifyOptionType option_type;
3623         int count,j;
3624         print_queue_struct *queue=NULL;
3625         print_status_struct status;
3626         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3627         WERROR result;
3628
3629         DEBUG(4,("printer_notify_info\n"));
3630
3631         if (!Printer)
3632                 return WERR_BADFID;
3633
3634         option = Printer->notify.option;
3635         id = 0x0;
3636
3637         info->version   = 2;
3638         info->notifies  = NULL;
3639         info->count     = 0;
3640
3641         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3642            sending a ffpcn() request first */
3643
3644         if ( !option )
3645                 return WERR_BADFID;
3646
3647         get_printer_snum(p, hnd, &snum, NULL);
3648
3649         /* Maybe we should use the SYSTEM session_info here... */
3650         result = winreg_get_printer(mem_ctx,
3651                                     get_session_info_system(),
3652                                     p->msg_ctx,
3653                                     lp_servicename(snum), &pinfo2);
3654         if (!W_ERROR_IS_OK(result)) {
3655                 return WERR_BADFID;
3656         }
3657
3658         for (i=0; i<option->count; i++) {
3659                 option_type = option->types[i];
3660
3661                 switch (option_type.type) {
3662                 case PRINTER_NOTIFY_TYPE:
3663                         if (construct_notify_printer_info(p->msg_ctx,
3664                                                           Printer, info,
3665                                                           pinfo2, snum,
3666                                                           &option_type, id,
3667                                                           mem_ctx)) {
3668                                 id--;
3669                         }
3670                         break;
3671
3672                 case JOB_NOTIFY_TYPE:
3673
3674                         count = print_queue_status(p->msg_ctx, snum, &queue,
3675                                                    &status);
3676
3677                         for (j=0; j<count; j++) {
3678                                 construct_notify_jobs_info(p->msg_ctx,
3679                                                            &queue[j], info,
3680                                                            pinfo2, snum,
3681                                                            &option_type,
3682                                                            queue[j].job,
3683                                                            mem_ctx);
3684                         }
3685
3686                         SAFE_FREE(queue);
3687                         break;
3688                 }
3689         }
3690
3691         /*
3692          * Debugging information, don't delete.
3693          */
3694         /*
3695         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3696         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3697         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3698
3699         for (i=0; i<info->count; i++) {
3700                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3701                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3702                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3703         }
3704         */
3705
3706         talloc_free(pinfo2);
3707         return WERR_OK;
3708 }
3709
3710 /****************************************************************
3711  _spoolss_RouterRefreshPrinterChangeNotify
3712 ****************************************************************/
3713
3714 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3715                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3716 {
3717         struct spoolss_NotifyInfo *info;
3718
3719         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3720         WERROR result = WERR_BADFID;
3721
3722         /* we always have a spoolss_NotifyInfo struct */
3723         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3724         if (!info) {
3725                 result = WERR_NOMEM;
3726                 goto done;
3727         }
3728
3729         *r->out.info = info;
3730
3731         if (!Printer) {
3732                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3733                         "Invalid handle (%s:%u:%u).\n",
3734                         OUR_HANDLE(r->in.handle)));
3735                 goto done;
3736         }
3737
3738         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3739
3740         /*
3741          *      We are now using the change value, and
3742          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3743          *      I don't have a global notification system, I'm sending back all the
3744          *      informations even when _NOTHING_ has changed.
3745          */
3746
3747         /* We need to keep track of the change value to send back in
3748            RRPCN replies otherwise our updates are ignored. */
3749
3750         Printer->notify.fnpcn = true;
3751
3752         if (Printer->notify.cli_chan != NULL &&
3753             Printer->notify.cli_chan->active_connections > 0) {
3754                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3755                         "Saving change value in request [%x]\n",
3756                         r->in.change_low));
3757                 Printer->notify.change = r->in.change_low;
3758         }
3759
3760         /* just ignore the spoolss_NotifyOption */
3761
3762         switch (Printer->printer_type) {
3763                 case SPLHND_SERVER:
3764                         result = printserver_notify_info(p, r->in.handle,
3765                                                          info, p->mem_ctx);
3766                         break;
3767
3768                 case SPLHND_PRINTER:
3769                         result = printer_notify_info(p, r->in.handle,
3770                                                      info, p->mem_ctx);
3771                         break;
3772         }
3773
3774         Printer->notify.fnpcn = false;
3775
3776 done:
3777         return result;
3778 }
3779
3780 /********************************************************************
3781  ********************************************************************/
3782
3783 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3784                                  const char *servername,
3785                                  const char *printername,
3786                                  const char **printername_p)
3787 {
3788         /* FIXME: add lp_force_printername() */
3789
3790         if (servername == NULL) {
3791                 *printername_p = talloc_strdup(mem_ctx, printername);
3792                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3793                 return WERR_OK;
3794         }
3795
3796         if (servername[0] == '\\' && servername[1] == '\\') {
3797                 servername += 2;
3798         }
3799
3800         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3801         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3802
3803         return WERR_OK;
3804 }
3805
3806 /********************************************************************
3807  ********************************************************************/
3808
3809 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3810                                           const char *printername)
3811 {
3812         if (dm == NULL) {
3813                 return;
3814         }
3815
3816         dm->devicename = talloc_strndup(dm, printername,
3817                                         MIN(strlen(printername), 31));
3818 }
3819
3820 /********************************************************************
3821  * construct_printer_info_0
3822  * fill a printer_info_0 struct
3823  ********************************************************************/
3824
3825 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3826                                       const struct auth_serversupplied_info *session_info,
3827                                       struct messaging_context *msg_ctx,
3828                                       struct spoolss_PrinterInfo2 *info2,
3829                                       const char *servername,
3830                                       struct spoolss_PrinterInfo0 *r,
3831                                       int snum)
3832 {
3833         int count;
3834         struct printer_session_counter *session_counter;
3835         struct timeval setuptime;
3836         print_status_struct status;
3837         WERROR result;
3838
3839         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3840         if (!W_ERROR_IS_OK(result)) {
3841                 return result;
3842         }
3843
3844         if (servername) {
3845                 r->servername = talloc_strdup(mem_ctx, servername);
3846                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3847         } else {
3848                 r->servername = NULL;
3849         }
3850
3851         count = print_queue_length(msg_ctx, snum, &status);
3852
3853         /* check if we already have a counter for this printer */
3854         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3855                 if (session_counter->snum == snum)
3856                         break;
3857         }
3858
3859         /* it's the first time, add it to the list */
3860         if (session_counter == NULL) {
3861                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3862                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3863                 session_counter->snum           = snum;
3864                 session_counter->counter        = 0;
3865                 DLIST_ADD(counter_list, session_counter);
3866         }
3867
3868         /* increment it */
3869         session_counter->counter++;
3870
3871         r->cjobs                        = count;
3872         r->total_jobs                   = 0;
3873         r->total_bytes                  = 0;
3874
3875         get_startup_time(&setuptime);
3876         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3877
3878         /* JFM:
3879          * the global_counter should be stored in a TDB as it's common to all the clients
3880          * and should be zeroed on samba startup
3881          */
3882         r->global_counter               = session_counter->counter;
3883         r->total_pages                  = 0;
3884         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3885         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3886         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3887         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3888         r->spooling                     = 0;
3889         r->max_spooling                 = 0;
3890         r->session_counter              = session_counter->counter;
3891         r->num_error_out_of_paper       = 0x0;
3892         r->num_error_not_ready          = 0x0;          /* number of print failure */
3893         r->job_error                    = 0x0;
3894         r->number_of_processors         = 0x1;
3895         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3896         r->high_part_total_bytes        = 0x0;
3897
3898         /* ChangeID in milliseconds*/
3899         winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3900                                     info2->sharename, &r->change_id);
3901
3902         r->last_error                   = WERR_OK;
3903         r->status                       = nt_printq_status(status.status);
3904         r->enumerate_network_printers   = 0x0;
3905         r->c_setprinter                 = 0x0;
3906         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3907         r->processor_level              = 0x6;          /* 6  ???*/
3908         r->ref_ic                       = 0;
3909         r->reserved2                    = 0;
3910         r->reserved3                    = 0;
3911
3912         return WERR_OK;
3913 }
3914
3915
3916 /********************************************************************
3917  * construct_printer_info1
3918  * fill a spoolss_PrinterInfo1 struct
3919 ********************************************************************/
3920
3921 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3922                                       const struct spoolss_PrinterInfo2 *info2,
3923                                       uint32_t flags,
3924                                       const char *servername,
3925                                       struct spoolss_PrinterInfo1 *r,
3926                                       int snum)
3927 {
3928         WERROR result;
3929
3930         r->flags                = flags;
3931
3932         if (info2->comment == NULL || info2->comment[0] == '\0') {
3933                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3934         } else {
3935                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3936         }
3937         W_ERROR_HAVE_NO_MEMORY(r->comment);
3938
3939         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3940         if (!W_ERROR_IS_OK(result)) {
3941                 return result;
3942         }
3943
3944         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3945                                                   r->name,
3946                                                   info2->drivername,
3947                                                   r->comment);
3948         W_ERROR_HAVE_NO_MEMORY(r->description);
3949
3950         return WERR_OK;
3951 }
3952
3953 /********************************************************************
3954  * construct_printer_info2
3955  * fill a spoolss_PrinterInfo2 struct
3956 ********************************************************************/
3957
3958 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3959                                       struct messaging_context *msg_ctx,
3960                                       const struct spoolss_PrinterInfo2 *info2,
3961                                       const char *servername,
3962                                       struct spoolss_PrinterInfo2 *r,
3963                                       int snum)
3964 {
3965         int count;
3966         print_status_struct status;
3967         WERROR result;
3968
3969         count = print_queue_length(msg_ctx, snum, &status);
3970
3971         if (servername) {
3972                 r->servername           = talloc_strdup(mem_ctx, servername);
3973                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3974         } else {
3975                 r->servername           = NULL;
3976         }
3977
3978         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3979         if (!W_ERROR_IS_OK(result)) {
3980                 return result;
3981         }
3982
3983         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3984         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3985         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3986         W_ERROR_HAVE_NO_MEMORY(r->portname);
3987         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3988         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3989
3990         if (info2->comment[0] == '\0') {
3991                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3992         } else {
3993                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3994         }
3995         W_ERROR_HAVE_NO_MEMORY(r->comment);
3996
3997         r->location             = talloc_strdup(mem_ctx, info2->location);
3998         W_ERROR_HAVE_NO_MEMORY(r->location);
3999         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4000         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4001         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4002         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4003         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4004         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4005         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4006         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4007
4008         r->attributes           = info2->attributes;
4009
4010         r->priority             = info2->priority;
4011         r->defaultpriority      = info2->defaultpriority;
4012         r->starttime            = info2->starttime;
4013         r->untiltime            = info2->untiltime;
4014         r->status               = nt_printq_status(status.status);
4015         r->cjobs                = count;
4016         r->averageppm           = info2->averageppm;
4017
4018         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4019         if (!r->devmode) {
4020                 DEBUG(8,("Returning NULL Devicemode!\n"));
4021         }
4022
4023         compose_devicemode_devicename(r->devmode, r->printername);
4024
4025         r->secdesc = NULL;
4026
4027         if (info2->secdesc != NULL) {
4028                 /* don't use talloc_steal() here unless you do a deep steal of all
4029                    the SEC_DESC members */
4030
4031                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4032         }
4033
4034         return WERR_OK;
4035 }
4036
4037 /********************************************************************
4038  * construct_printer_info3
4039  * fill a spoolss_PrinterInfo3 struct
4040  ********************************************************************/
4041
4042 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4043                                       const struct spoolss_PrinterInfo2 *info2,
4044                                       const char *servername,
4045                                       struct spoolss_PrinterInfo3 *r,
4046                                       int snum)
4047 {
4048         /* These are the components of the SD we are returning. */
4049
4050         if (info2->secdesc != NULL) {
4051                 /* don't use talloc_steal() here unless you do a deep steal of all
4052                    the SEC_DESC members */
4053
4054                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4055                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4056         }
4057
4058         return WERR_OK;
4059 }
4060
4061 /********************************************************************
4062  * construct_printer_info4
4063  * fill a spoolss_PrinterInfo4 struct
4064  ********************************************************************/
4065
4066 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4067                                       const struct spoolss_PrinterInfo2 *info2,
4068                                       const char *servername,
4069                                       struct spoolss_PrinterInfo4 *r,
4070                                       int snum)
4071 {
4072         WERROR result;
4073
4074         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4075         if (!W_ERROR_IS_OK(result)) {
4076                 return result;
4077         }
4078
4079         if (servername) {
4080                 r->servername   = talloc_strdup(mem_ctx, servername);
4081                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4082         } else {
4083                 r->servername = NULL;
4084         }
4085
4086         r->attributes   = info2->attributes;
4087
4088         return WERR_OK;
4089 }
4090
4091 /********************************************************************
4092  * construct_printer_info5
4093  * fill a spoolss_PrinterInfo5 struct
4094  ********************************************************************/
4095
4096 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4097                                       const struct spoolss_PrinterInfo2 *info2,
4098                                       const char *servername,
4099                                       struct spoolss_PrinterInfo5 *r,
4100                                       int snum)
4101 {
4102         WERROR result;
4103
4104         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4105         if (!W_ERROR_IS_OK(result)) {
4106                 return result;
4107         }
4108
4109         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4110         W_ERROR_HAVE_NO_MEMORY(r->portname);
4111
4112         r->attributes   = info2->attributes;
4113
4114         /* these two are not used by NT+ according to MSDN */
4115         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4116         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4117
4118         return WERR_OK;
4119 }
4120
4121 /********************************************************************
4122  * construct_printer_info_6
4123  * fill a spoolss_PrinterInfo6 struct
4124  ********************************************************************/
4125
4126 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4127                                       struct messaging_context *msg_ctx,
4128                                       const struct spoolss_PrinterInfo2 *info2,
4129                                       const char *servername,
4130                                       struct spoolss_PrinterInfo6 *r,
4131                                       int snum)
4132 {
4133         int count;
4134         print_status_struct status;
4135
4136         count = print_queue_length(msg_ctx, snum, &status);
4137
4138         r->status = nt_printq_status(status.status);
4139
4140         return WERR_OK;
4141 }
4142
4143 /********************************************************************
4144  * construct_printer_info7
4145  * fill a spoolss_PrinterInfo7 struct
4146  ********************************************************************/
4147
4148 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4149                                       struct messaging_context *msg_ctx,
4150                                       const char *servername,
4151                                       struct spoolss_PrinterInfo7 *r,
4152                                       int snum)
4153 {
4154         struct auth_serversupplied_info *session_info;
4155         struct GUID guid;
4156         NTSTATUS status;
4157
4158         status = make_session_info_system(mem_ctx, &session_info);
4159         if (!NT_STATUS_IS_OK(status)) {
4160                 DEBUG(0, ("construct_printer_info7: "
4161                           "Could not create system session_info\n"));
4162                 return WERR_NOMEM;
4163         }
4164
4165         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4166                                  servername,
4167                                  lp_servicename(snum), &guid, NULL)) {
4168                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4169                 r->action = DSPRINT_PUBLISH;
4170         } else {
4171                 r->guid = talloc_strdup(mem_ctx, "");
4172                 r->action = DSPRINT_UNPUBLISH;
4173         }
4174         W_ERROR_HAVE_NO_MEMORY(r->guid);
4175
4176         TALLOC_FREE(session_info);
4177         return WERR_OK;
4178 }
4179
4180 /********************************************************************
4181  * construct_printer_info8
4182  * fill a spoolss_PrinterInfo8 struct
4183  ********************************************************************/
4184
4185 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4186                                       const struct spoolss_PrinterInfo2 *info2,
4187                                       const char *servername,
4188                                       struct spoolss_DeviceModeInfo *r,
4189                                       int snum)
4190 {
4191         WERROR result;
4192         const char *printername;
4193
4194         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4195         if (!W_ERROR_IS_OK(result)) {
4196                 return result;
4197         }
4198
4199         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4200         if (!r->devmode) {
4201                 DEBUG(8,("Returning NULL Devicemode!\n"));
4202         }
4203
4204         compose_devicemode_devicename(r->devmode, printername);
4205
4206         return WERR_OK;
4207 }
4208
4209
4210 /********************************************************************
4211 ********************************************************************/
4212
4213 static bool snum_is_shared_printer(int snum)
4214 {
4215         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4216 }
4217
4218 /********************************************************************
4219  Spoolss_enumprinters.
4220 ********************************************************************/
4221
4222 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4223                                            const struct auth_serversupplied_info *session_info,
4224                                            struct messaging_context *msg_ctx,
4225                                            const char *servername,
4226                                            uint32_t level,
4227                                            uint32_t flags,
4228                                            union spoolss_PrinterInfo **info_p,
4229                                            uint32_t *count_p)
4230 {
4231         int snum;
4232         int n_services = lp_numservices();
4233         union spoolss_PrinterInfo *info = NULL;
4234         uint32_t count = 0;
4235         WERROR result = WERR_OK;
4236
4237         *count_p = 0;
4238         *info_p = NULL;
4239
4240         for (snum = 0; snum < n_services; snum++) {
4241
4242                 const char *printer;
4243                 struct spoolss_PrinterInfo2 *info2;
4244
4245                 if (!snum_is_shared_printer(snum)) {
4246                         continue;
4247                 }
4248
4249                 printer = lp_const_servicename(snum);
4250
4251                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4252                         printer, snum));
4253
4254                 result = winreg_create_printer(mem_ctx,
4255                                                session_info,
4256                                                msg_ctx,
4257                                                printer);
4258                 if (!W_ERROR_IS_OK(result)) {
4259                         goto out;
4260                 }
4261
4262                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4263                                             union spoolss_PrinterInfo,
4264                                             count + 1);
4265                 if (!info) {
4266                         result = WERR_NOMEM;
4267                         goto out;
4268                 }
4269
4270                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4271                                             printer, &info2);
4272                 if (!W_ERROR_IS_OK(result)) {
4273                         goto out;
4274                 }
4275
4276                 switch (level) {
4277                 case 0:
4278                         result = construct_printer_info0(info, session_info,
4279                                                          msg_ctx, info2,
4280                                                          servername,
4281                                                          &info[count].info0, snum);
4282                         break;
4283                 case 1:
4284                         result = construct_printer_info1(info, info2, flags,
4285                                                          servername,
4286                                                          &info[count].info1, snum);
4287                         break;
4288                 case 2:
4289                         result = construct_printer_info2(info, msg_ctx, info2,
4290                                                          servername,
4291                                                          &info[count].info2, snum);
4292                         break;
4293                 case 4:
4294                         result = construct_printer_info4(info, info2,
4295                                                          servername,
4296                                                          &info[count].info4, snum);
4297                         break;
4298                 case 5:
4299                         result = construct_printer_info5(info, info2,
4300                                                          servername,
4301                                                          &info[count].info5, snum);
4302                         break;
4303
4304                 default:
4305                         result = WERR_UNKNOWN_LEVEL;
4306                         goto out;
4307                 }
4308
4309                 if (!W_ERROR_IS_OK(result)) {
4310                         goto out;
4311                 }
4312
4313                 count++;
4314         }
4315
4316         *count_p = count;
4317         *info_p = info;
4318
4319  out:
4320         if (!W_ERROR_IS_OK(result)) {
4321                 TALLOC_FREE(info);
4322                 return result;
4323         }
4324
4325         *info_p = info;
4326
4327         return WERR_OK;
4328 }
4329
4330 /********************************************************************
4331  * handle enumeration of printers at level 0
4332  ********************************************************************/
4333
4334 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4335                                   const struct auth_serversupplied_info *session_info,
4336                                   struct messaging_context *msg_ctx,
4337                                   uint32_t flags,
4338                                   const char *servername,
4339                                   union spoolss_PrinterInfo **info,
4340                                   uint32_t *count)
4341 {
4342         DEBUG(4,("enum_all_printers_info_0\n"));
4343
4344         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4345                                             servername, 0, flags, info, count);
4346 }
4347
4348
4349 /********************************************************************
4350 ********************************************************************/
4351
4352 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4353                                        const struct auth_serversupplied_info *session_info,
4354                                        struct messaging_context *msg_ctx,
4355                                        const char *servername,
4356                                        uint32_t flags,
4357                                        union spoolss_PrinterInfo **info,
4358                                        uint32_t *count)
4359 {
4360         DEBUG(4,("enum_all_printers_info_1\n"));
4361
4362         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4363                                             servername, 1, flags, info, count);
4364 }
4365
4366 /********************************************************************
4367  enum_all_printers_info_1_local.
4368 *********************************************************************/
4369
4370 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4371                                              const struct auth_serversupplied_info *session_info,
4372                                              struct messaging_context *msg_ctx,
4373                                              const char *servername,
4374                                              union spoolss_PrinterInfo **info,
4375                                              uint32_t *count)
4376 {
4377         DEBUG(4,("enum_all_printers_info_1_local\n"));
4378
4379         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4380                                         servername, PRINTER_ENUM_ICON8, info, count);
4381 }
4382
4383 /********************************************************************
4384  enum_all_printers_info_1_name.
4385 *********************************************************************/
4386
4387 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4388                                             const struct auth_serversupplied_info *session_info,
4389                                             struct messaging_context *msg_ctx,
4390                                             const char *servername,
4391                                             union spoolss_PrinterInfo **info,
4392                                             uint32_t *count)
4393 {
4394         const char *s = servername;
4395
4396         DEBUG(4,("enum_all_printers_info_1_name\n"));
4397
4398         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4399                 s = servername + 2;
4400         }
4401
4402         if (!is_myname_or_ipaddr(s)) {
4403                 return WERR_INVALID_NAME;
4404         }
4405
4406         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4407                                         servername, PRINTER_ENUM_ICON8, info, count);
4408 }
4409
4410 /********************************************************************
4411  enum_all_printers_info_1_network.
4412 *********************************************************************/
4413
4414 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4415                                                const struct auth_serversupplied_info *session_info,
4416                                                struct messaging_context *msg_ctx,
4417                                                const char *servername,
4418                                                union spoolss_PrinterInfo **info,
4419                                                uint32_t *count)
4420 {
4421         const char *s = servername;
4422
4423         DEBUG(4,("enum_all_printers_info_1_network\n"));
4424
4425         /* If we respond to a enum_printers level 1 on our name with flags
4426            set to PRINTER_ENUM_REMOTE with a list of printers then these
4427            printers incorrectly appear in the APW browse list.
4428            Specifically the printers for the server appear at the workgroup
4429            level where all the other servers in the domain are
4430            listed. Windows responds to this call with a
4431            WERR_CAN_NOT_COMPLETE so we should do the same. */
4432
4433         if (servername[0] == '\\' && servername[1] == '\\') {
4434                  s = servername + 2;
4435         }
4436
4437         if (is_myname_or_ipaddr(s)) {
4438                  return WERR_CAN_NOT_COMPLETE;
4439         }
4440
4441         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4442                                         servername, PRINTER_ENUM_NAME, info, count);
4443 }
4444
4445 /********************************************************************
4446  * api_spoolss_enumprinters
4447  *
4448  * called from api_spoolss_enumprinters (see this to understand)
4449  ********************************************************************/
4450
4451 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4452                                        const struct auth_serversupplied_info *session_info,
4453                                        struct messaging_context *msg_ctx,
4454                                        const char *servername,
4455                                        union spoolss_PrinterInfo **info,
4456                                        uint32_t *count)
4457 {
4458         DEBUG(4,("enum_all_printers_info_2\n"));
4459
4460         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4461                                             servername, 2, 0, info, count);
4462 }
4463
4464 /********************************************************************
4465  * handle enumeration of printers at level 1
4466  ********************************************************************/
4467
4468 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4469                                   const struct auth_serversupplied_info *session_info,
4470                                   struct messaging_context *msg_ctx,
4471                                   uint32_t flags,
4472                                   const char *servername,
4473                                   union spoolss_PrinterInfo **info,
4474                                   uint32_t *count)
4475 {
4476         /* Not all the flags are equals */
4477
4478         if (flags & PRINTER_ENUM_LOCAL) {
4479                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4480                                                       msg_ctx, servername, info, count);
4481         }
4482
4483         if (flags & PRINTER_ENUM_NAME) {
4484                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4485                                                      msg_ctx, servername, info,
4486                                                      count);
4487         }
4488
4489         if (flags & PRINTER_ENUM_NETWORK) {
4490                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4491                                                         msg_ctx, servername, info,
4492                                                         count);
4493         }
4494
4495         return WERR_OK; /* NT4sp5 does that */
4496 }
4497
4498 /********************************************************************
4499  * handle enumeration of printers at level 2
4500  ********************************************************************/
4501
4502 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4503                                   const struct auth_serversupplied_info *session_info,
4504                                   struct messaging_context *msg_ctx,
4505                                   uint32_t flags,
4506                                   const char *servername,
4507                                   union spoolss_PrinterInfo **info,
4508                                   uint32_t *count)
4509 {
4510         if (flags & PRINTER_ENUM_LOCAL) {
4511
4512                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4513                                                 servername,
4514                                                 info, count);
4515         }
4516
4517         if (flags & PRINTER_ENUM_NAME) {
4518                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4519                         return WERR_INVALID_NAME;
4520                 }
4521
4522                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4523                                                 servername,
4524                                                 info, count);
4525         }
4526
4527         if (flags & PRINTER_ENUM_REMOTE) {
4528                 return WERR_UNKNOWN_LEVEL;
4529         }
4530
4531         return WERR_OK;
4532 }
4533
4534 /********************************************************************
4535  * handle enumeration of printers at level 4
4536  ********************************************************************/
4537
4538 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4539                                   const struct auth_serversupplied_info *session_info,
4540                                   struct messaging_context *msg_ctx,
4541                                   uint32_t flags,
4542                                   const char *servername,
4543                                   union spoolss_PrinterInfo **info,
4544                                   uint32_t *count)
4545 {
4546         DEBUG(4,("enum_all_printers_info_4\n"));
4547
4548         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4549                                             servername, 4, flags, info, count);
4550 }
4551
4552
4553 /********************************************************************
4554  * handle enumeration of printers at level 5
4555  ********************************************************************/
4556
4557 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4558                                   const struct auth_serversupplied_info *session_info,
4559                                   struct messaging_context *msg_ctx,
4560                                   uint32_t flags,
4561                                   const char *servername,
4562                                   union spoolss_PrinterInfo **info,
4563                                   uint32_t *count)
4564 {
4565         DEBUG(4,("enum_all_printers_info_5\n"));
4566
4567         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4568                                             servername, 5, flags, info, count);
4569 }
4570
4571 /****************************************************************
4572  _spoolss_EnumPrinters
4573 ****************************************************************/
4574
4575 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4576                              struct spoolss_EnumPrinters *r)
4577 {
4578         const struct auth_serversupplied_info *session_info = get_session_info_system();
4579         WERROR result;
4580
4581         /* that's an [in out] buffer */
4582
4583         if (!r->in.buffer && (r->in.offered != 0)) {
4584                 return WERR_INVALID_PARAM;
4585         }
4586
4587         DEBUG(4,("_spoolss_EnumPrinters\n"));
4588
4589         *r->out.needed = 0;
4590         *r->out.count = 0;
4591         *r->out.info = NULL;
4592
4593         /*
4594          * Level 1:
4595          *          flags==PRINTER_ENUM_NAME
4596          *           if name=="" then enumerates all printers
4597          *           if name!="" then enumerate the printer
4598          *          flags==PRINTER_ENUM_REMOTE
4599          *          name is NULL, enumerate printers
4600          * Level 2: name!="" enumerates printers, name can't be NULL
4601          * Level 3: doesn't exist
4602          * Level 4: does a local registry lookup
4603          * Level 5: same as Level 2
4604          */
4605
4606         if (r->in.server && r->in.server[0] == '\0') {
4607                 r->in.server = NULL;
4608         }
4609
4610         switch (r->in.level) {
4611         case 0:
4612                 result = enumprinters_level0(p->mem_ctx, session_info,
4613                                              p->msg_ctx, r->in.flags,
4614                                              r->in.server,
4615                                              r->out.info, r->out.count);
4616                 break;
4617         case 1:
4618                 result = enumprinters_level1(p->mem_ctx, session_info,
4619                                              p->msg_ctx, r->in.flags,
4620                                              r->in.server,
4621                                              r->out.info, r->out.count);
4622                 break;
4623         case 2:
4624                 result = enumprinters_level2(p->mem_ctx, session_info,
4625                                              p->msg_ctx, r->in.flags,
4626                                              r->in.server,
4627                                              r->out.info, r->out.count);
4628                 break;
4629         case 4:
4630                 result = enumprinters_level4(p->mem_ctx, session_info,
4631                                              p->msg_ctx, r->in.flags,
4632                                              r->in.server,
4633                                              r->out.info, r->out.count);
4634                 break;
4635         case 5:
4636                 result = enumprinters_level5(p->mem_ctx, session_info,
4637                                              p->msg_ctx, r->in.flags,
4638                                              r->in.server,
4639                                              r->out.info, r->out.count);
4640                 break;
4641         default:
4642                 return WERR_UNKNOWN_LEVEL;
4643         }
4644
4645         if (!W_ERROR_IS_OK(result)) {
4646                 return result;
4647         }
4648
4649         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4650                                                      spoolss_EnumPrinters,
4651                                                      *r->out.info, r->in.level,
4652                                                      *r->out.count);
4653         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4654         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4655
4656         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4657 }
4658
4659 /****************************************************************
4660  _spoolss_GetPrinter
4661 ****************************************************************/
4662
4663 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4664                            struct spoolss_GetPrinter *r)
4665 {
4666         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4667         struct spoolss_PrinterInfo2 *info2 = NULL;
4668         WERROR result = WERR_OK;
4669         int snum;
4670
4671         /* that's an [in out] buffer */
4672
4673         if (!r->in.buffer && (r->in.offered != 0)) {
4674                 return WERR_INVALID_PARAM;
4675         }
4676
4677         *r->out.needed = 0;
4678
4679         if (Printer == NULL) {
4680                 return WERR_BADFID;
4681         }
4682
4683         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4684                 return WERR_BADFID;
4685         }
4686
4687         result = winreg_get_printer(p->mem_ctx,
4688                                     get_session_info_system(),
4689                                     p->msg_ctx,
4690                                     lp_const_servicename(snum),
4691                                     &info2);
4692         if (!W_ERROR_IS_OK(result)) {
4693                 goto out;
4694         }
4695
4696         switch (r->in.level) {
4697         case 0:
4698                 result = construct_printer_info0(p->mem_ctx,
4699                                                  get_session_info_system(),
4700                                                  p->msg_ctx,
4701                                                  info2,
4702                                                  Printer->servername,
4703                                                  &r->out.info->info0,
4704                                                  snum);
4705                 break;
4706         case 1:
4707                 result = construct_printer_info1(p->mem_ctx, info2,
4708                                                  PRINTER_ENUM_ICON8,
4709                                                  Printer->servername,
4710                                                  &r->out.info->info1, snum);
4711                 break;
4712         case 2:
4713                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4714                                                  Printer->servername,
4715                                                  &r->out.info->info2, snum);
4716                 break;
4717         case 3:
4718                 result = construct_printer_info3(p->mem_ctx, info2,
4719                                                  Printer->servername,
4720                                                  &r->out.info->info3, snum);
4721                 break;
4722         case 4:
4723                 result = construct_printer_info4(p->mem_ctx, info2,
4724                                                  Printer->servername,
4725                                                  &r->out.info->info4, snum);
4726                 break;
4727         case 5:
4728                 result = construct_printer_info5(p->mem_ctx, info2,
4729                                                  Printer->servername,
4730                                                  &r->out.info->info5, snum);
4731                 break;
4732         case 6:
4733                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4734                                                  Printer->servername,
4735                                                  &r->out.info->info6, snum);
4736                 break;
4737         case 7:
4738                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4739                                                  Printer->servername,
4740                                                  &r->out.info->info7, snum);
4741                 break;
4742         case 8:
4743                 result = construct_printer_info8(p->mem_ctx, info2,
4744                                                  Printer->servername,
4745                                                  &r->out.info->info8, snum);
4746                 break;
4747         default:
4748                 result = WERR_UNKNOWN_LEVEL;
4749                 break;
4750         }
4751
4752  out:
4753         if (!W_ERROR_IS_OK(result)) {
4754                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4755                           r->in.level, win_errstr(result)));
4756                 TALLOC_FREE(r->out.info);
4757                 return result;
4758         }
4759
4760         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4761                                                r->out.info, r->in.level);
4762         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4763
4764         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4765 }
4766
4767 /********************************************************************
4768  ********************************************************************/
4769
4770 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4771         do { \
4772                 if (in && strlen(in)) { \
4773                         out = talloc_strdup(mem_ctx, in); \
4774                 } else { \
4775                         out = talloc_strdup(mem_ctx, ""); \
4776                 } \
4777                 W_ERROR_HAVE_NO_MEMORY(out); \
4778         } while (0);
4779
4780 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4781         do { \
4782                 if (in && strlen(in)) { \
4783                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4784                 } else { \
4785                         out = talloc_strdup(mem_ctx, ""); \
4786                 } \
4787                 W_ERROR_HAVE_NO_MEMORY(out); \
4788         } while (0);
4789
4790 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4791                                                   const char **string_array,
4792                                                   const char ***presult,
4793                                                   const char *cservername,
4794                                                   const char *arch,
4795                                                   int version)
4796 {
4797         int i, num_strings = 0;
4798         const char **array = NULL;
4799
4800         if (string_array == NULL) {
4801                 return WERR_INVALID_PARAMETER;
4802         }
4803
4804         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4805                 const char *str = NULL;
4806
4807                 if (cservername == NULL || arch == NULL) {
4808                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4809                 } else {
4810                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4811                 }
4812
4813                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4814                         TALLOC_FREE(array);
4815                         return WERR_NOMEM;
4816                 }
4817         }
4818
4819         if (i > 0) {
4820                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4821                              &array, &num_strings);
4822         }
4823
4824         if (presult) {
4825                 *presult = array;
4826         }
4827
4828         return WERR_OK;
4829 }
4830
4831 /********************************************************************
4832  * fill a spoolss_DriverInfo1 struct
4833  ********************************************************************/
4834
4835 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4836                                         struct spoolss_DriverInfo1 *r,
4837                                         const struct spoolss_DriverInfo8 *driver,
4838                                         const char *servername)
4839 {
4840         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4841         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4842
4843         return WERR_OK;
4844 }
4845
4846 /********************************************************************
4847  * fill a spoolss_DriverInfo2 struct
4848  ********************************************************************/
4849
4850 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4851                                         struct spoolss_DriverInfo2 *r,
4852                                         const struct spoolss_DriverInfo8 *driver,
4853                                         const char *servername)
4854
4855 {
4856         const char *cservername = canon_servername(servername);
4857
4858         r->version              = driver->version;
4859
4860         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4861         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4862         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4863         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4864
4865         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4866                                driver->architecture,
4867                                driver->version,
4868                                driver->driver_path,
4869                                r->driver_path);
4870
4871         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4872                                driver->architecture,
4873                                driver->version,
4874                                driver->data_file,
4875                                r->data_file);
4876
4877         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4878                                driver->architecture,
4879                                driver->version,
4880                                driver->config_file,
4881                                r->config_file);
4882
4883         return WERR_OK;
4884 }
4885
4886 /********************************************************************
4887  * fill a spoolss_DriverInfo3 struct
4888  ********************************************************************/
4889
4890 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4891                                         struct spoolss_DriverInfo3 *r,
4892                                         const struct spoolss_DriverInfo8 *driver,
4893                                         const char *servername)
4894 {
4895         const char *cservername = canon_servername(servername);
4896
4897         r->version              = driver->version;
4898
4899         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4900         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4901         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4902         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4903
4904         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4905                                driver->architecture,
4906                                driver->version,
4907                                driver->driver_path,
4908                                r->driver_path);
4909
4910         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4911                                driver->architecture,
4912                                driver->version,
4913                                driver->data_file,
4914                                r->data_file);
4915
4916         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4917                                driver->architecture,
4918                                driver->version,
4919                                driver->config_file,
4920                                r->config_file);
4921
4922         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4923                                driver->architecture,
4924                                driver->version,
4925                                driver->help_file,
4926                                r->help_file);
4927
4928         FILL_DRIVER_STRING(mem_ctx,
4929                            driver->monitor_name,
4930                            r->monitor_name);
4931
4932         FILL_DRIVER_STRING(mem_ctx,
4933                            driver->default_datatype,
4934                            r->default_datatype);
4935
4936         return string_array_from_driver_info(mem_ctx,
4937                                              driver->dependent_files,
4938                                              &r->dependent_files,
4939                                              cservername,
4940                                              driver->architecture,
4941                                              driver->version);
4942 }
4943
4944 /********************************************************************
4945  * fill a spoolss_DriverInfo4 struct
4946  ********************************************************************/
4947
4948 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4949                                         struct spoolss_DriverInfo4 *r,
4950                                         const struct spoolss_DriverInfo8 *driver,
4951                                         const char *servername)
4952 {
4953         const char *cservername = canon_servername(servername);
4954         WERROR result;
4955
4956         r->version              = driver->version;
4957
4958         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4959         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4960         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4961         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4962
4963         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4964                                driver->architecture,
4965                                driver->version,
4966                                driver->driver_path,
4967                                r->driver_path);
4968
4969         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4970                                driver->architecture,
4971                                driver->version,
4972                                driver->data_file,
4973                                r->data_file);
4974
4975         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4976                                driver->architecture,
4977                                driver->version,
4978                                driver->config_file,
4979                                r->config_file);
4980
4981         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4982                                driver->architecture,
4983                                driver->version,
4984                                driver->help_file,
4985                                r->help_file);
4986
4987         result = string_array_from_driver_info(mem_ctx,
4988                                                driver->dependent_files,
4989                                                &r->dependent_files,
4990                                                cservername,
4991                                                driver->architecture,
4992                                                driver->version);
4993         if (!W_ERROR_IS_OK(result)) {
4994                 return result;
4995         }
4996
4997         FILL_DRIVER_STRING(mem_ctx,
4998                            driver->monitor_name,
4999                            r->monitor_name);
5000
5001         FILL_DRIVER_STRING(mem_ctx,
5002                            driver->default_datatype,
5003                            r->default_datatype);
5004
5005
5006         result = string_array_from_driver_info(mem_ctx,
5007                                                driver->previous_names,
5008                                                &r->previous_names,
5009                                                NULL, NULL, 0);
5010
5011         return result;
5012 }
5013
5014 /********************************************************************
5015  * fill a spoolss_DriverInfo5 struct
5016  ********************************************************************/
5017
5018 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5019                                         struct spoolss_DriverInfo5 *r,
5020                                         const struct spoolss_DriverInfo8 *driver,
5021                                         const char *servername)
5022 {
5023         const char *cservername = canon_servername(servername);
5024
5025         r->version              = driver->version;
5026
5027         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5028         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5029         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5030         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5031
5032         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5033                                driver->architecture,
5034                                driver->version,
5035                                driver->driver_path,
5036                                r->driver_path);
5037
5038         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5039                                driver->architecture,
5040                                driver->version,
5041                                driver->data_file,
5042                                r->data_file);
5043
5044         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5045                                driver->architecture,
5046                                driver->version,
5047                                driver->config_file,
5048                                r->config_file);
5049
5050         r->driver_attributes    = 0;
5051         r->config_version       = 0;
5052         r->driver_version       = 0;
5053
5054         return WERR_OK;
5055 }
5056 /********************************************************************
5057  * fill a spoolss_DriverInfo6 struct
5058  ********************************************************************/
5059
5060 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5061                                         struct spoolss_DriverInfo6 *r,
5062                                         const struct spoolss_DriverInfo8 *driver,
5063                                         const char *servername)
5064 {
5065         const char *cservername = canon_servername(servername);
5066         WERROR result;
5067
5068         r->version              = driver->version;
5069
5070         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5071         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5072         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5073         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5074
5075         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5076                                driver->architecture,
5077                                driver->version,
5078                                driver->driver_path,
5079                                r->driver_path);
5080
5081         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5082                                driver->architecture,
5083                                driver->version,
5084                                driver->data_file,
5085                                r->data_file);
5086
5087         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5088                                driver->architecture,
5089                                driver->version,
5090                                driver->config_file,
5091                                r->config_file);
5092
5093         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5094                                driver->architecture,
5095                                driver->version,
5096                                driver->help_file,
5097                                r->help_file);
5098
5099         FILL_DRIVER_STRING(mem_ctx,
5100                            driver->monitor_name,
5101                            r->monitor_name);
5102
5103         FILL_DRIVER_STRING(mem_ctx,
5104                            driver->default_datatype,
5105                            r->default_datatype);
5106
5107         result = string_array_from_driver_info(mem_ctx,
5108                                                driver->dependent_files,
5109                                                &r->dependent_files,
5110                                                cservername,
5111                                                driver->architecture,
5112                                                driver->version);
5113         if (!W_ERROR_IS_OK(result)) {
5114                 return result;
5115         }
5116
5117         result = string_array_from_driver_info(mem_ctx,
5118                                                driver->previous_names,
5119                                                &r->previous_names,
5120                                                NULL, NULL, 0);
5121         if (!W_ERROR_IS_OK(result)) {
5122                 return result;
5123         }
5124
5125         r->driver_date          = driver->driver_date;
5126         r->driver_version       = driver->driver_version;
5127
5128         FILL_DRIVER_STRING(mem_ctx,
5129                            driver->manufacturer_name,
5130                            r->manufacturer_name);
5131         FILL_DRIVER_STRING(mem_ctx,
5132                            driver->manufacturer_url,
5133                            r->manufacturer_url);
5134         FILL_DRIVER_STRING(mem_ctx,
5135                            driver->hardware_id,
5136                            r->hardware_id);
5137         FILL_DRIVER_STRING(mem_ctx,
5138                            driver->provider,
5139                            r->provider);
5140
5141         return WERR_OK;
5142 }
5143
5144 /********************************************************************
5145  * fill a spoolss_DriverInfo8 struct
5146  ********************************************************************/
5147
5148 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5149                                         struct spoolss_DriverInfo8 *r,
5150                                         const struct spoolss_DriverInfo8 *driver,
5151                                         const char *servername)
5152 {
5153         const char *cservername = canon_servername(servername);
5154         WERROR result;
5155
5156         r->version              = driver->version;
5157
5158         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5159         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5160         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5161         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5162
5163         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5164                                driver->architecture,
5165                                driver->version,
5166                                driver->driver_path,
5167                                r->driver_path);
5168
5169         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5170                                driver->architecture,
5171                                driver->version,
5172                                driver->data_file,
5173                                r->data_file);
5174
5175         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5176                                driver->architecture,
5177                                driver->version,
5178                                driver->config_file,
5179                                r->config_file);
5180
5181         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5182                                driver->architecture,
5183                                driver->version,
5184                                driver->help_file,
5185                                r->help_file);
5186
5187         FILL_DRIVER_STRING(mem_ctx,
5188                            driver->monitor_name,
5189                            r->monitor_name);
5190
5191         FILL_DRIVER_STRING(mem_ctx,
5192                            driver->default_datatype,
5193                            r->default_datatype);
5194
5195         result = string_array_from_driver_info(mem_ctx,
5196                                                driver->dependent_files,
5197                                                &r->dependent_files,
5198                                                cservername,
5199                                                driver->architecture,
5200                                                driver->version);
5201         if (!W_ERROR_IS_OK(result)) {
5202                 return result;
5203         }
5204
5205         result = string_array_from_driver_info(mem_ctx,
5206                                                driver->previous_names,
5207                                                &r->previous_names,
5208                                                NULL, NULL, 0);
5209         if (!W_ERROR_IS_OK(result)) {
5210                 return result;
5211         }
5212
5213         r->driver_date          = driver->driver_date;
5214         r->driver_version       = driver->driver_version;
5215
5216         FILL_DRIVER_STRING(mem_ctx,
5217                            driver->manufacturer_name,
5218                            r->manufacturer_name);
5219         FILL_DRIVER_STRING(mem_ctx,
5220                            driver->manufacturer_url,
5221                            r->manufacturer_url);
5222         FILL_DRIVER_STRING(mem_ctx,
5223                            driver->hardware_id,
5224                            r->hardware_id);
5225         FILL_DRIVER_STRING(mem_ctx,
5226                            driver->provider,
5227                            r->provider);
5228
5229         FILL_DRIVER_STRING(mem_ctx,
5230                            driver->print_processor,
5231                            r->print_processor);
5232         FILL_DRIVER_STRING(mem_ctx,
5233                            driver->vendor_setup,
5234                            r->vendor_setup);
5235
5236         result = string_array_from_driver_info(mem_ctx,
5237                                                driver->color_profiles,
5238                                                &r->color_profiles,
5239                                                NULL, NULL, 0);
5240         if (!W_ERROR_IS_OK(result)) {
5241                 return result;
5242         }
5243
5244         FILL_DRIVER_STRING(mem_ctx,
5245                            driver->inf_path,
5246                            r->inf_path);
5247
5248         r->printer_driver_attributes    = driver->printer_driver_attributes;
5249
5250         result = string_array_from_driver_info(mem_ctx,
5251                                                driver->core_driver_dependencies,
5252                                                &r->core_driver_dependencies,
5253                                                NULL, NULL, 0);
5254         if (!W_ERROR_IS_OK(result)) {
5255                 return result;
5256         }
5257
5258         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5259         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5260
5261         return WERR_OK;
5262 }
5263
5264 #if 0 /* disabled until marshalling issues are resolved - gd */
5265 /********************************************************************
5266  ********************************************************************/
5267
5268 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5269                                           struct spoolss_DriverFileInfo *r,
5270                                           const char *cservername,
5271                                           const char *file_name,
5272                                           enum spoolss_DriverFileType file_type,
5273                                           uint32_t file_version)
5274 {
5275         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5276                                           cservername, file_name);
5277         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5278         r->file_type    = file_type;
5279         r->file_version = file_version;
5280
5281         return WERR_OK;
5282 }
5283
5284 /********************************************************************
5285  ********************************************************************/
5286
5287 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5288                                                  const struct spoolss_DriverInfo8 *driver,
5289                                                  const char *cservername,
5290                                                  struct spoolss_DriverFileInfo **info_p,
5291                                                  uint32_t *count_p)
5292 {
5293         struct spoolss_DriverFileInfo *info = NULL;
5294         uint32_t count = 0;
5295         WERROR result;
5296         uint32_t i;
5297
5298         *info_p = NULL;
5299         *count_p = 0;
5300
5301         if (strlen(driver->driver_path)) {
5302                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5303                                             struct spoolss_DriverFileInfo,
5304                                             count + 1);
5305                 W_ERROR_HAVE_NO_MEMORY(info);
5306                 result = fill_spoolss_DriverFileInfo(info,
5307                                                      &info[count],
5308                                                      cservername,
5309                                                      driver->driver_path,
5310                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5311                                                      0);
5312                 W_ERROR_NOT_OK_RETURN(result);
5313                 count++;
5314         }
5315
5316         if (strlen(driver->config_file)) {
5317                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5318                                             struct spoolss_DriverFileInfo,
5319                                             count + 1);
5320                 W_ERROR_HAVE_NO_MEMORY(info);
5321                 result = fill_spoolss_DriverFileInfo(info,
5322                                                      &info[count],
5323                                                      cservername,
5324                                                      driver->config_file,
5325                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5326                                                      0);
5327                 W_ERROR_NOT_OK_RETURN(result);
5328                 count++;
5329         }
5330
5331         if (strlen(driver->data_file)) {
5332                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5333                                             struct spoolss_DriverFileInfo,
5334                                             count + 1);
5335                 W_ERROR_HAVE_NO_MEMORY(info);
5336                 result = fill_spoolss_DriverFileInfo(info,
5337                                                      &info[count],
5338                                                      cservername,
5339                                                      driver->data_file,
5340                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5341                                                      0);
5342                 W_ERROR_NOT_OK_RETURN(result);
5343                 count++;
5344         }
5345
5346         if (strlen(driver->help_file)) {
5347                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5348                                             struct spoolss_DriverFileInfo,
5349                                             count + 1);
5350                 W_ERROR_HAVE_NO_MEMORY(info);
5351                 result = fill_spoolss_DriverFileInfo(info,
5352                                                      &info[count],
5353                                                      cservername,
5354                                                      driver->help_file,
5355                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5356                                                      0);
5357                 W_ERROR_NOT_OK_RETURN(result);
5358                 count++;
5359         }
5360
5361         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5362                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5363                                             struct spoolss_DriverFileInfo,
5364                                             count + 1);
5365                 W_ERROR_HAVE_NO_MEMORY(info);
5366                 result = fill_spoolss_DriverFileInfo(info,
5367                                                      &info[count],
5368                                                      cservername,
5369                                                      driver->dependent_files[i],
5370                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5371                                                      0);
5372                 W_ERROR_NOT_OK_RETURN(result);
5373                 count++;
5374         }
5375
5376         *info_p = info;
5377         *count_p = count;
5378
5379         return WERR_OK;
5380 }
5381
5382 /********************************************************************
5383  * fill a spoolss_DriverInfo101 struct
5384  ********************************************************************/
5385
5386 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5387                                           struct spoolss_DriverInfo101 *r,
5388                                           const struct spoolss_DriverInfo8 *driver,
5389                                           const char *servername)
5390 {
5391         const char *cservername = canon_servername(servername);
5392         WERROR result;
5393
5394         r->version              = driver->version;
5395
5396         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5397         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5398         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5399         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5400
5401         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5402                                                     cservername,
5403                                                     &r->file_info,
5404                                                     &r->file_count);
5405         if (!W_ERROR_IS_OK(result)) {
5406                 return result;
5407         }
5408
5409         FILL_DRIVER_STRING(mem_ctx,
5410                            driver->monitor_name,
5411                            r->monitor_name);
5412
5413         FILL_DRIVER_STRING(mem_ctx,
5414                            driver->default_datatype,
5415                            r->default_datatype);
5416
5417         result = string_array_from_driver_info(mem_ctx,
5418                                                driver->previous_names,
5419                                                &r->previous_names,
5420                                                NULL, NULL, 0);
5421         if (!W_ERROR_IS_OK(result)) {
5422                 return result;
5423         }
5424
5425         r->driver_date          = driver->driver_date;
5426         r->driver_version       = driver->driver_version;
5427
5428         FILL_DRIVER_STRING(mem_ctx,
5429                            driver->manufacturer_name,
5430                            r->manufacturer_name);
5431         FILL_DRIVER_STRING(mem_ctx,
5432                            driver->manufacturer_url,
5433                            r->manufacturer_url);
5434         FILL_DRIVER_STRING(mem_ctx,
5435                            driver->hardware_id,
5436                            r->hardware_id);
5437         FILL_DRIVER_STRING(mem_ctx,
5438                            driver->provider,
5439                            r->provider);
5440
5441         return WERR_OK;
5442 }
5443 #endif
5444 /********************************************************************
5445  ********************************************************************/
5446
5447 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5448                                                   const struct auth_serversupplied_info *session_info,
5449                                                   struct messaging_context *msg_ctx,
5450                                                   uint32_t level,
5451                                                   union spoolss_DriverInfo *r,
5452                                                   int snum,
5453                                                   const char *servername,
5454                                                   const char *architecture,
5455                                                   uint32_t version)
5456 {
5457         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5458         struct spoolss_DriverInfo8 *driver;
5459         WERROR result;
5460
5461         if (level == 101) {
5462                 return WERR_UNKNOWN_LEVEL;
5463         }
5464
5465         result = winreg_get_printer(mem_ctx,
5466                                     session_info,
5467                                     msg_ctx,
5468                                     lp_const_servicename(snum),
5469                                     &pinfo2);
5470
5471         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5472                 win_errstr(result)));
5473
5474         if (!W_ERROR_IS_OK(result)) {
5475                 return WERR_INVALID_PRINTER_NAME;
5476         }
5477
5478         result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5479                                    architecture,
5480                                    pinfo2->drivername, version, &driver);
5481
5482         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5483                 win_errstr(result)));
5484
5485         if (!W_ERROR_IS_OK(result)) {
5486                 /*
5487                  * Is this a W2k client ?
5488                  */
5489
5490                 if (version < 3) {
5491                         talloc_free(pinfo2);
5492                         return WERR_UNKNOWN_PRINTER_DRIVER;
5493                 }
5494
5495                 /* Yes - try again with a WinNT driver. */
5496                 version = 2;
5497                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5498                                            architecture,
5499                                            pinfo2->drivername,
5500                                            version, &driver);
5501                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5502                         win_errstr(result)));
5503                 if (!W_ERROR_IS_OK(result)) {
5504                         talloc_free(pinfo2);
5505                         return WERR_UNKNOWN_PRINTER_DRIVER;
5506                 }
5507         }
5508
5509         switch (level) {
5510         case 1:
5511                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5512                 break;
5513         case 2:
5514                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5515                 break;
5516         case 3:
5517                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5518                 break;
5519         case 4:
5520                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5521                 break;
5522         case 5:
5523                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5524                 break;
5525         case 6:
5526                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5527                 break;
5528         case 8:
5529                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5530                 break;
5531 #if 0 /* disabled until marshalling issues are resolved - gd */
5532         case 101:
5533                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5534                 break;
5535 #endif
5536         default:
5537                 result = WERR_UNKNOWN_LEVEL;
5538                 break;
5539         }
5540
5541         talloc_free(pinfo2);
5542         talloc_free(driver);
5543
5544         return result;
5545 }
5546
5547 /****************************************************************
5548  _spoolss_GetPrinterDriver2
5549 ****************************************************************/
5550
5551 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5552                                   struct spoolss_GetPrinterDriver2 *r)
5553 {
5554         struct printer_handle *printer;
5555         WERROR result;
5556
5557         int snum;
5558
5559         /* that's an [in out] buffer */
5560
5561         if (!r->in.buffer && (r->in.offered != 0)) {
5562                 return WERR_INVALID_PARAM;
5563         }
5564
5565         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5566
5567         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5568                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5569                 return WERR_INVALID_PRINTER_NAME;
5570         }
5571
5572         *r->out.needed = 0;
5573         *r->out.server_major_version = 0;
5574         *r->out.server_minor_version = 0;
5575
5576         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5577                 return WERR_BADFID;
5578         }
5579
5580         result = construct_printer_driver_info_level(p->mem_ctx,
5581                                                      get_session_info_system(),
5582                                                      p->msg_ctx,
5583                                                      r->in.level, r->out.info,
5584                                                      snum, printer->servername,
5585                                                      r->in.architecture,
5586                                                      r->in.client_major_version);
5587         if (!W_ERROR_IS_OK(result)) {
5588                 TALLOC_FREE(r->out.info);
5589                 return result;
5590         }
5591
5592         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5593                                                r->out.info, r->in.level);
5594         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5595
5596         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5597 }
5598
5599
5600 /****************************************************************
5601  _spoolss_StartPagePrinter
5602 ****************************************************************/
5603
5604 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5605                                  struct spoolss_StartPagePrinter *r)
5606 {
5607         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5608
5609         if (!Printer) {
5610                 DEBUG(3,("_spoolss_StartPagePrinter: "
5611                         "Error in startpageprinter printer handle\n"));
5612                 return WERR_BADFID;
5613         }
5614
5615         Printer->page_started = true;
5616         return WERR_OK;
5617 }
5618
5619 /****************************************************************
5620  _spoolss_EndPagePrinter
5621 ****************************************************************/
5622
5623 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5624                                struct spoolss_EndPagePrinter *r)
5625 {
5626         int snum;
5627
5628         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5629
5630         if (!Printer) {
5631                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5632                         OUR_HANDLE(r->in.handle)));
5633                 return WERR_BADFID;
5634         }
5635
5636         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5637                 return WERR_BADFID;
5638
5639         Printer->page_started = false;
5640         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5641
5642         return WERR_OK;
5643 }
5644
5645 /****************************************************************
5646  _spoolss_StartDocPrinter
5647 ****************************************************************/
5648
5649 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5650                                 struct spoolss_StartDocPrinter *r)
5651 {
5652         struct spoolss_DocumentInfo1 *info_1;
5653         int snum;
5654         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5655         WERROR werr;
5656
5657         if (!Printer) {
5658                 DEBUG(2,("_spoolss_StartDocPrinter: "
5659                         "Invalid handle (%s:%u:%u)\n",
5660                         OUR_HANDLE(r->in.handle)));
5661                 return WERR_BADFID;
5662         }
5663
5664         if (Printer->jobid) {
5665                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5666                           "StartDocPrinter called twice! "
5667                           "(existing jobid = %d)\n", Printer->jobid));
5668                 return WERR_INVALID_HANDLE;
5669         }
5670
5671         if (r->in.level != 1) {
5672                 return WERR_UNKNOWN_LEVEL;
5673         }
5674
5675         info_1 = r->in.info.info1;
5676
5677         /*
5678          * a nice thing with NT is it doesn't listen to what you tell it.
5679          * when asked to send _only_ RAW datas, it tries to send datas
5680          * in EMF format.
5681          *
5682          * So I add checks like in NT Server ...
5683          */
5684
5685         if (info_1->datatype) {
5686                 if (strcmp(info_1->datatype, "RAW") != 0) {
5687                         *r->out.job_id = 0;
5688                         return WERR_INVALID_DATATYPE;
5689                 }
5690         }
5691
5692         /* get the share number of the printer */
5693         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5694                 return WERR_BADFID;
5695         }
5696
5697         werr = print_job_start(p->session_info,
5698                                p->msg_ctx,
5699                                p->client_id->name,
5700                                snum,
5701                                info_1->document_name,
5702                                info_1->output_file,
5703                                Printer->devmode,
5704                                &Printer->jobid);
5705
5706         /* An error occured in print_job_start() so return an appropriate
5707            NT error code. */
5708
5709         if (!W_ERROR_IS_OK(werr)) {
5710                 return werr;
5711         }
5712
5713         Printer->document_started = true;
5714         *r->out.job_id = Printer->jobid;
5715
5716         return WERR_OK;
5717 }
5718
5719 /****************************************************************
5720  _spoolss_EndDocPrinter
5721 ****************************************************************/
5722
5723 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5724                               struct spoolss_EndDocPrinter *r)
5725 {
5726         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5727         NTSTATUS status;
5728         int snum;
5729
5730         if (!Printer) {
5731                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5732                         OUR_HANDLE(r->in.handle)));
5733                 return WERR_BADFID;
5734         }
5735
5736         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5737                 return WERR_BADFID;
5738         }
5739
5740         Printer->document_started = false;
5741         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5742         if (!NT_STATUS_IS_OK(status)) {
5743                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5744                           "print_job_end failed [%s]\n",
5745                           nt_errstr(status)));
5746         }
5747
5748         Printer->jobid = 0;
5749         return ntstatus_to_werror(status);
5750 }
5751
5752 /****************************************************************
5753  _spoolss_WritePrinter
5754 ****************************************************************/
5755
5756 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5757                              struct spoolss_WritePrinter *r)
5758 {
5759         ssize_t buffer_written;
5760         int snum;
5761         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5762
5763         if (!Printer) {
5764                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5765                         OUR_HANDLE(r->in.handle)));
5766                 *r->out.num_written = r->in._data_size;
5767                 return WERR_BADFID;
5768         }
5769
5770         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5771                 return WERR_BADFID;
5772
5773         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5774         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5775                                                    snum, Printer->jobid,
5776                                                    (const char *)r->in.data.data,
5777                                                    (size_t)r->in._data_size);
5778         if (buffer_written == (ssize_t)-1) {
5779                 *r->out.num_written = 0;
5780                 if (errno == ENOSPC)
5781                         return WERR_NO_SPOOL_SPACE;
5782                 else
5783                         return WERR_ACCESS_DENIED;
5784         }
5785
5786         *r->out.num_written = r->in._data_size;
5787
5788         return WERR_OK;
5789 }
5790
5791 /********************************************************************
5792  * api_spoolss_getprinter
5793  * called from the spoolss dispatcher
5794  *
5795  ********************************************************************/
5796
5797 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5798                               struct pipes_struct *p)
5799 {
5800         const struct auth_serversupplied_info *session_info = p->session_info;
5801         int snum;
5802         WERROR errcode = WERR_BADFUNC;
5803         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5804
5805         if (!Printer) {
5806                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5807                         OUR_HANDLE(handle)));
5808                 return WERR_BADFID;
5809         }
5810
5811         if (!get_printer_snum(p, handle, &snum, NULL))
5812                 return WERR_BADFID;
5813
5814         switch (command) {
5815         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5816                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5817                 break;
5818         case SPOOLSS_PRINTER_CONTROL_RESUME:
5819         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5820                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5821                 break;
5822         case SPOOLSS_PRINTER_CONTROL_PURGE:
5823                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5824                 break;
5825         default:
5826                 return WERR_UNKNOWN_LEVEL;
5827         }
5828
5829         return errcode;
5830 }
5831
5832
5833 /****************************************************************
5834  _spoolss_AbortPrinter
5835  * From MSDN: "Deletes printer's spool file if printer is configured
5836  * for spooling"
5837 ****************************************************************/
5838
5839 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5840                              struct spoolss_AbortPrinter *r)
5841 {
5842         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5843         int             snum;
5844         WERROR          errcode = WERR_OK;
5845
5846         if (!Printer) {
5847                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5848                         OUR_HANDLE(r->in.handle)));
5849                 return WERR_BADFID;
5850         }
5851
5852         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5853                 return WERR_BADFID;
5854
5855         if (!Printer->document_started) {
5856                 return WERR_SPL_NO_STARTDOC;
5857         }
5858
5859         errcode = print_job_delete(p->session_info,
5860                                    p->msg_ctx,
5861                                    snum,
5862                                    Printer->jobid);
5863
5864         return errcode;
5865 }
5866
5867 /********************************************************************
5868  * called by spoolss_api_setprinter
5869  * when updating a printer description
5870  ********************************************************************/
5871
5872 static WERROR update_printer_sec(struct policy_handle *handle,
5873                                  struct pipes_struct *p,
5874                                  struct sec_desc_buf *secdesc_ctr)
5875 {
5876         struct spoolss_security_descriptor *new_secdesc = NULL;
5877         struct spoolss_security_descriptor *old_secdesc = NULL;
5878         const char *printer;
5879         WERROR result;
5880         int snum;
5881
5882         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5883
5884         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5885                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5886                          OUR_HANDLE(handle)));
5887
5888                 result = WERR_BADFID;
5889                 goto done;
5890         }
5891
5892         if (secdesc_ctr == NULL) {
5893                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5894                 result = WERR_INVALID_PARAM;
5895                 goto done;
5896         }
5897         printer = lp_const_servicename(snum);
5898
5899         /* Check the user has permissions to change the security
5900            descriptor.  By experimentation with two NT machines, the user
5901            requires Full Access to the printer to change security
5902            information. */
5903
5904         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5905                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5906                 result = WERR_ACCESS_DENIED;
5907                 goto done;
5908         }
5909
5910         /* NT seems to like setting the security descriptor even though
5911            nothing may have actually changed. */
5912         result = winreg_get_printer_secdesc(p->mem_ctx,
5913                                             get_session_info_system(),
5914                                             p->msg_ctx,
5915                                             printer,
5916                                             &old_secdesc);
5917         if (!W_ERROR_IS_OK(result)) {
5918                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5919                 result = WERR_BADFID;
5920                 goto done;
5921         }
5922
5923         if (DEBUGLEVEL >= 10) {
5924                 struct security_acl *the_acl;
5925                 int i;
5926
5927                 the_acl = old_secdesc->dacl;
5928                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5929                            printer, the_acl->num_aces));
5930
5931                 for (i = 0; i < the_acl->num_aces; i++) {
5932                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5933                                            &the_acl->aces[i].trustee),
5934                                   the_acl->aces[i].access_mask));
5935                 }
5936
5937                 the_acl = secdesc_ctr->sd->dacl;
5938
5939                 if (the_acl) {
5940                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5941                                    printer, the_acl->num_aces));
5942
5943                         for (i = 0; i < the_acl->num_aces; i++) {
5944                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5945                                                    &the_acl->aces[i].trustee),
5946                                            the_acl->aces[i].access_mask));
5947                         }
5948                 } else {
5949                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5950                 }
5951         }
5952
5953         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5954         if (new_secdesc == NULL) {
5955                 result = WERR_NOMEM;
5956                 goto done;
5957         }
5958
5959         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5960                 result = WERR_OK;
5961                 goto done;
5962         }
5963
5964         result = winreg_set_printer_secdesc(p->mem_ctx,
5965                                             get_session_info_system(),
5966                                             p->msg_ctx,
5967                                             printer,
5968                                             new_secdesc);
5969
5970  done:
5971         return result;
5972 }
5973
5974 /********************************************************************
5975  Canonicalize printer info from a client
5976  ********************************************************************/
5977
5978 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5979                              struct spoolss_SetPrinterInfo2 *info2,
5980                              int snum)
5981 {
5982         fstring printername;
5983         const char *p;
5984
5985         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5986                 "portname=%s drivername=%s comment=%s location=%s\n",
5987                 info2->servername, info2->printername, info2->sharename,
5988                 info2->portname, info2->drivername, info2->comment,
5989                 info2->location));
5990
5991         /* we force some elements to "correct" values */
5992         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5993         if (info2->servername == NULL) {
5994                 return false;
5995         }
5996         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5997         if (info2->sharename == NULL) {
5998                 return false;
5999         }
6000
6001         /* check to see if we allow printername != sharename */
6002         if (lp_force_printername(snum)) {
6003                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6004                                         global_myname(), info2->sharename);
6005         } else {
6006                 /* make sure printername is in \\server\printername format */
6007                 fstrcpy(printername, info2->printername);
6008                 p = printername;
6009                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6010                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6011                                 p++;
6012                 }
6013
6014                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6015                                         global_myname(), p);
6016         }
6017         if (info2->printername == NULL) {
6018                 return false;
6019         }
6020
6021         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6022         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6023
6024         return true;
6025 }
6026
6027 /****************************************************************************
6028 ****************************************************************************/
6029
6030 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6031 {
6032         char *cmd = lp_addport_cmd();
6033         char *command = NULL;
6034         int ret;
6035         bool is_print_op = false;
6036
6037         if ( !*cmd ) {
6038                 return WERR_ACCESS_DENIED;
6039         }
6040
6041         command = talloc_asprintf(ctx,
6042                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6043         if (!command) {
6044                 return WERR_NOMEM;
6045         }
6046
6047         if ( token )
6048                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6049
6050         DEBUG(10,("Running [%s]\n", command));
6051
6052         /********* BEGIN SePrintOperatorPrivilege **********/
6053
6054         if ( is_print_op )
6055                 become_root();
6056
6057         ret = smbrun(command, NULL);
6058
6059         if ( is_print_op )
6060                 unbecome_root();
6061
6062         /********* END SePrintOperatorPrivilege **********/
6063
6064         DEBUGADD(10,("returned [%d]\n", ret));
6065
6066         TALLOC_FREE(command);
6067
6068         if ( ret != 0 ) {
6069                 return WERR_ACCESS_DENIED;
6070         }
6071
6072         return WERR_OK;
6073 }
6074
6075 /****************************************************************************
6076 ****************************************************************************/
6077
6078 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6079                              struct spoolss_SetPrinterInfo2 *info2,
6080                              const char *remote_machine,
6081                              struct messaging_context *msg_ctx)
6082 {
6083         char *cmd = lp_addprinter_cmd();
6084         char **qlines;
6085         char *command = NULL;
6086         int numlines;
6087         int ret;
6088         int fd;
6089         bool is_print_op = false;
6090
6091         if (!remote_machine) {
6092                 return false;
6093         }
6094
6095         command = talloc_asprintf(ctx,
6096                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6097                         cmd, info2->printername, info2->sharename,
6098                         info2->portname, info2->drivername,
6099                         info2->location, info2->comment, remote_machine);
6100         if (!command) {
6101                 return false;
6102         }
6103
6104         if ( token )
6105                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6106
6107         DEBUG(10,("Running [%s]\n", command));
6108
6109         /********* BEGIN SePrintOperatorPrivilege **********/
6110
6111         if ( is_print_op )
6112                 become_root();
6113
6114         if ( (ret = smbrun(command, &fd)) == 0 ) {
6115                 /* Tell everyone we updated smb.conf. */
6116                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6117         }
6118
6119         if ( is_print_op )
6120                 unbecome_root();
6121
6122         /********* END SePrintOperatorPrivilege **********/
6123
6124         DEBUGADD(10,("returned [%d]\n", ret));
6125
6126         TALLOC_FREE(command);
6127
6128         if ( ret != 0 ) {
6129                 if (fd != -1)
6130                         close(fd);
6131                 return false;
6132         }
6133
6134         /* reload our services immediately */
6135         become_root();
6136         reload_services(msg_ctx, -1, false);
6137         unbecome_root();
6138
6139         numlines = 0;
6140         /* Get lines and convert them back to dos-codepage */
6141         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6142         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6143         close(fd);
6144
6145         /* Set the portname to what the script says the portname should be. */
6146         /* but don't require anything to be return from the script exit a good error code */
6147
6148         if (numlines) {
6149                 /* Set the portname to what the script says the portname should be. */
6150                 info2->portname = talloc_strdup(ctx, qlines[0]);
6151                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6152         }
6153
6154         TALLOC_FREE(qlines);
6155         return true;
6156 }
6157
6158 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6159                                const struct auth_serversupplied_info *session_info,
6160                                struct messaging_context *msg_ctx,
6161                                int snum,
6162                                struct spoolss_SetPrinterInfo2 *printer,
6163                                struct spoolss_PrinterInfo2 *old_printer)
6164 {
6165         bool force_update = (old_printer == NULL);
6166         const char *dnsdomname;
6167         const char *longname;
6168         const char *uncname;
6169         const char *spooling;
6170         DATA_BLOB buffer;
6171         WERROR result = WERR_OK;
6172
6173         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6174                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6175                 winreg_set_printer_dataex(mem_ctx,
6176                                           session_info,
6177                                           msg_ctx,
6178                                           printer->sharename,
6179                                           SPOOL_DSSPOOLER_KEY,
6180                                           SPOOL_REG_DRIVERNAME,
6181                                           REG_SZ,
6182                                           buffer.data,
6183                                           buffer.length);
6184
6185                 if (!force_update) {
6186                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6187                                 printer->drivername));
6188
6189                         notify_printer_driver(server_event_context(), msg_ctx,
6190                                               snum, printer->drivername ?
6191                                               printer->drivername : "");
6192                 }
6193         }
6194
6195         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6196                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6197                 winreg_set_printer_dataex(mem_ctx,
6198                                           session_info,
6199                                           msg_ctx,
6200                                           printer->sharename,
6201                                           SPOOL_DSSPOOLER_KEY,
6202                                           SPOOL_REG_DESCRIPTION,
6203                                           REG_SZ,
6204                                           buffer.data,
6205                                           buffer.length);
6206
6207                 if (!force_update) {
6208                         notify_printer_comment(server_event_context(), msg_ctx,
6209                                                snum, printer->comment ?
6210                                                printer->comment : "");
6211                 }
6212         }
6213
6214         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6215                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6216                 winreg_set_printer_dataex(mem_ctx,
6217                                           session_info,
6218                                           msg_ctx,
6219                                           printer->sharename,
6220                                           SPOOL_DSSPOOLER_KEY,
6221                                           SPOOL_REG_PRINTSHARENAME,
6222                                           REG_SZ,
6223                                           buffer.data,
6224                                           buffer.length);
6225
6226                 if (!force_update) {
6227                         notify_printer_sharename(server_event_context(),
6228                                                  msg_ctx,
6229                                                  snum, printer->sharename ?
6230                                                  printer->sharename : "");
6231                 }
6232         }
6233
6234         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6235                 const char *p;
6236
6237                 p = strrchr(printer->printername, '\\' );
6238                 if (p != NULL) {
6239                         p++;
6240                 } else {
6241                         p = printer->printername;
6242                 }
6243
6244                 push_reg_sz(mem_ctx, &buffer, p);
6245                 winreg_set_printer_dataex(mem_ctx,
6246                                           session_info,
6247                                           msg_ctx,
6248                                           printer->sharename,
6249                                           SPOOL_DSSPOOLER_KEY,
6250                                           SPOOL_REG_PRINTERNAME,
6251                                           REG_SZ,
6252                                           buffer.data,
6253                                           buffer.length);
6254
6255                 if (!force_update) {
6256                         notify_printer_printername(server_event_context(),
6257                                                    msg_ctx, snum, p ? p : "");
6258                 }
6259         }
6260
6261         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6262                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6263                 winreg_set_printer_dataex(mem_ctx,
6264                                           session_info,
6265                                           msg_ctx,
6266                                           printer->sharename,
6267                                           SPOOL_DSSPOOLER_KEY,
6268                                           SPOOL_REG_PORTNAME,
6269                                           REG_SZ,
6270                                           buffer.data,
6271                                           buffer.length);
6272
6273                 if (!force_update) {
6274                         notify_printer_port(server_event_context(),
6275                                             msg_ctx, snum, printer->portname ?
6276                                             printer->portname : "");
6277                 }
6278         }
6279
6280         if (force_update || !strequal(printer->location, old_printer->location)) {
6281                 push_reg_sz(mem_ctx, &buffer, printer->location);
6282                 winreg_set_printer_dataex(mem_ctx,
6283                                           session_info,
6284                                           msg_ctx,
6285                                           printer->sharename,
6286                                           SPOOL_DSSPOOLER_KEY,
6287                                           SPOOL_REG_LOCATION,
6288                                           REG_SZ,
6289                                           buffer.data,
6290                                           buffer.length);
6291
6292                 if (!force_update) {
6293                         notify_printer_location(server_event_context(),
6294                                                 msg_ctx, snum,
6295                                                 printer->location ?
6296                                                 printer->location : "");
6297                 }
6298         }
6299
6300         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6301                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6302                 winreg_set_printer_dataex(mem_ctx,
6303                                           session_info,
6304                                           msg_ctx,
6305                                           printer->sharename,
6306                                           SPOOL_DSSPOOLER_KEY,
6307                                           SPOOL_REG_PRINTSEPARATORFILE,
6308                                           REG_SZ,
6309                                           buffer.data,
6310                                           buffer.length);
6311
6312                 if (!force_update) {
6313                         notify_printer_sepfile(server_event_context(),
6314                                                msg_ctx, snum,
6315                                                printer->sepfile ?
6316                                                printer->sepfile : "");
6317                 }
6318         }
6319
6320         if (force_update || printer->starttime != old_printer->starttime) {
6321                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6322                 SIVAL(buffer.data, 0, printer->starttime);
6323                 winreg_set_printer_dataex(mem_ctx,
6324                                           session_info,
6325                                           msg_ctx,
6326                                           printer->sharename,
6327                                           SPOOL_DSSPOOLER_KEY,
6328                                           SPOOL_REG_PRINTSTARTTIME,
6329                                           REG_DWORD,
6330                                           buffer.data,
6331                                           buffer.length);
6332         }
6333
6334         if (force_update || printer->untiltime != old_printer->untiltime) {
6335                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6336                 SIVAL(buffer.data, 0, printer->untiltime);
6337                 winreg_set_printer_dataex(mem_ctx,
6338                                           session_info,
6339                                           msg_ctx,
6340                                           printer->sharename,
6341                                           SPOOL_DSSPOOLER_KEY,
6342                                           SPOOL_REG_PRINTENDTIME,
6343                                           REG_DWORD,
6344                                           buffer.data,
6345                                           buffer.length);
6346         }
6347
6348         if (force_update || printer->priority != old_printer->priority) {
6349                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6350                 SIVAL(buffer.data, 0, printer->priority);
6351                 winreg_set_printer_dataex(mem_ctx,
6352                                           session_info,
6353                                           msg_ctx,
6354                                           printer->sharename,
6355                                           SPOOL_DSSPOOLER_KEY,
6356                                           SPOOL_REG_PRIORITY,
6357                                           REG_DWORD,
6358                                           buffer.data,
6359                                           buffer.length);
6360         }
6361
6362         if (force_update || printer->attributes != old_printer->attributes) {
6363                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6364                 SIVAL(buffer.data, 0, (printer->attributes &
6365                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6366                 winreg_set_printer_dataex(mem_ctx,
6367                                           session_info,
6368                                           msg_ctx,
6369                                           printer->sharename,
6370                                           SPOOL_DSSPOOLER_KEY,
6371                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6372                                           REG_DWORD,
6373                                           buffer.data,
6374                                           buffer.length);
6375
6376                 switch (printer->attributes & 0x3) {
6377                         case 0:
6378                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6379                                 break;
6380                         case 1:
6381                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6382                                 break;
6383                         case 2:
6384                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6385                                 break;
6386                         default:
6387                                 spooling = "unknown";
6388                 }
6389                 push_reg_sz(mem_ctx, &buffer, spooling);
6390                 winreg_set_printer_dataex(mem_ctx,
6391                                           session_info,
6392                                           msg_ctx,
6393                                           printer->sharename,
6394                                           SPOOL_DSSPOOLER_KEY,
6395                                           SPOOL_REG_PRINTSPOOLING,
6396                                           REG_SZ,
6397                                           buffer.data,
6398                                           buffer.length);
6399         }
6400
6401         push_reg_sz(mem_ctx, &buffer, global_myname());
6402         winreg_set_printer_dataex(mem_ctx,
6403                                   session_info,
6404                                   msg_ctx,
6405                                   printer->sharename,
6406                                   SPOOL_DSSPOOLER_KEY,
6407                                   SPOOL_REG_SHORTSERVERNAME,
6408                                   REG_SZ,
6409                                   buffer.data,
6410                                   buffer.length);
6411
6412         dnsdomname = get_mydnsfullname();
6413         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6414                 longname = talloc_strdup(mem_ctx, dnsdomname);
6415         } else {
6416                 longname = talloc_strdup(mem_ctx, global_myname());
6417         }
6418         if (longname == NULL) {
6419                 result = WERR_NOMEM;
6420                 goto done;
6421         }
6422
6423         push_reg_sz(mem_ctx, &buffer, longname);
6424         winreg_set_printer_dataex(mem_ctx,
6425                                   session_info,
6426                                   msg_ctx,
6427                                   printer->sharename,
6428                                   SPOOL_DSSPOOLER_KEY,
6429                                   SPOOL_REG_SERVERNAME,
6430                                   REG_SZ,
6431                                   buffer.data,
6432                                   buffer.length);
6433
6434         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6435                                   global_myname(), printer->sharename);
6436         push_reg_sz(mem_ctx, &buffer, uncname);
6437         winreg_set_printer_dataex(mem_ctx,
6438                                   session_info,
6439                                   msg_ctx,
6440                                   printer->sharename,
6441                                   SPOOL_DSSPOOLER_KEY,
6442                                   SPOOL_REG_UNCNAME,
6443                                   REG_SZ,
6444                                   buffer.data,
6445                                   buffer.length);
6446
6447 done:
6448         return result;
6449 }
6450
6451 /********************************************************************
6452  * Called by spoolss_api_setprinter
6453  * when updating a printer description.
6454  ********************************************************************/
6455
6456 static WERROR update_printer(struct pipes_struct *p,
6457                              struct policy_handle *handle,
6458                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6459                              struct spoolss_DeviceMode *devmode)
6460 {
6461         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6462         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6463         struct spoolss_PrinterInfo2 *old_printer;
6464         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6465         int snum;
6466         WERROR result = WERR_OK;
6467         TALLOC_CTX *tmp_ctx;
6468
6469         DEBUG(8,("update_printer\n"));
6470
6471         tmp_ctx = talloc_new(p->mem_ctx);
6472         if (tmp_ctx == NULL) {
6473                 return WERR_NOMEM;
6474         }
6475
6476         if (!Printer) {
6477                 result = WERR_BADFID;
6478                 goto done;
6479         }
6480
6481         if (!get_printer_snum(p, handle, &snum, NULL)) {
6482                 result = WERR_BADFID;
6483                 goto done;
6484         }
6485
6486         result = winreg_get_printer(tmp_ctx,
6487                                     get_session_info_system(),
6488                                     p->msg_ctx,
6489                                     lp_const_servicename(snum),
6490                                     &old_printer);
6491         if (!W_ERROR_IS_OK(result)) {
6492                 result = WERR_BADFID;
6493                 goto done;
6494         }
6495
6496         /* Do sanity check on the requested changes for Samba */
6497         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6498                 result = WERR_INVALID_PARAM;
6499                 goto done;
6500         }
6501
6502         /* FIXME!!! If the driver has changed we really should verify that
6503            it is installed before doing much else   --jerry */
6504
6505         /* Check calling user has permission to update printer description */
6506         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6507                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6508                 result = WERR_ACCESS_DENIED;
6509                 goto done;
6510         }
6511
6512         /* Call addprinter hook */
6513         /* Check changes to see if this is really needed */
6514
6515         if (*lp_addprinter_cmd() &&
6516                         (!strequal(printer->drivername, old_printer->drivername) ||
6517                          !strequal(printer->comment, old_printer->comment) ||
6518                          !strequal(printer->portname, old_printer->portname) ||
6519                          !strequal(printer->location, old_printer->location)) )
6520         {
6521                 /* add_printer_hook() will call reload_services() */
6522                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6523                                       printer, p->client_id->addr,
6524                                       p->msg_ctx)) {
6525                         result = WERR_ACCESS_DENIED;
6526                         goto done;
6527                 }
6528         }
6529
6530         update_dsspooler(tmp_ctx,
6531                          get_session_info_system(),
6532                          p->msg_ctx,
6533                          snum,
6534                          printer,
6535                          old_printer);
6536
6537         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6538
6539         if (devmode == NULL) {
6540                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6541         }
6542         result = winreg_update_printer(tmp_ctx,
6543                                        get_session_info_system(),
6544                                        p->msg_ctx,
6545                                        printer->sharename,
6546                                        printer_mask,
6547                                        printer,
6548                                        devmode,
6549                                        NULL);
6550
6551 done:
6552         talloc_free(tmp_ctx);
6553
6554         return result;
6555 }
6556
6557 /****************************************************************************
6558 ****************************************************************************/
6559 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6560                                            struct policy_handle *handle,
6561                                            struct spoolss_SetPrinterInfo7 *info7)
6562 {
6563 #ifdef HAVE_ADS
6564         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6565         WERROR result;
6566         int snum;
6567         struct printer_handle *Printer;
6568
6569         if ( lp_security() != SEC_ADS ) {
6570                 return WERR_UNKNOWN_LEVEL;
6571         }
6572
6573         Printer = find_printer_index_by_hnd(p, handle);
6574
6575         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6576
6577         if (!Printer)
6578                 return WERR_BADFID;
6579
6580         if (!get_printer_snum(p, handle, &snum, NULL))
6581                 return WERR_BADFID;
6582
6583         result = winreg_get_printer(p->mem_ctx,
6584                                     get_session_info_system(),
6585                                     p->msg_ctx,
6586                                     lp_servicename(snum),
6587                                     &pinfo2);
6588         if (!W_ERROR_IS_OK(result)) {
6589                 return WERR_BADFID;
6590         }
6591
6592         nt_printer_publish(pinfo2,
6593                            get_session_info_system(),
6594                            p->msg_ctx,
6595                            pinfo2,
6596                            info7->action);
6597
6598         TALLOC_FREE(pinfo2);
6599         return WERR_OK;
6600 #else
6601         return WERR_UNKNOWN_LEVEL;
6602 #endif
6603 }
6604
6605 /********************************************************************
6606  ********************************************************************/
6607
6608 static WERROR update_printer_devmode(struct pipes_struct *p,
6609                                      struct policy_handle *handle,
6610                                      struct spoolss_DeviceMode *devmode)
6611 {
6612         int snum;
6613         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6614         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6615
6616         DEBUG(8,("update_printer_devmode\n"));
6617
6618         if (!Printer) {
6619                 return WERR_BADFID;
6620         }
6621
6622         if (!get_printer_snum(p, handle, &snum, NULL)) {
6623                 return WERR_BADFID;
6624         }
6625
6626         /* Check calling user has permission to update printer description */
6627         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6628                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6629                 return WERR_ACCESS_DENIED;
6630         }
6631
6632         return winreg_update_printer(p->mem_ctx,
6633                                      get_session_info_system(),
6634                                      p->msg_ctx,
6635                                      lp_const_servicename(snum),
6636                                      info2_mask,
6637                                      NULL,
6638                                      devmode,
6639                                      NULL);
6640 }
6641
6642
6643 /****************************************************************
6644  _spoolss_SetPrinter
6645 ****************************************************************/
6646
6647 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6648                            struct spoolss_SetPrinter *r)
6649 {
6650         WERROR result;
6651
6652         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6653
6654         if (!Printer) {
6655                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6656                         OUR_HANDLE(r->in.handle)));
6657                 return WERR_BADFID;
6658         }
6659
6660         /* check the level */
6661         switch (r->in.info_ctr->level) {
6662                 case 0:
6663                         return control_printer(r->in.handle, r->in.command, p);
6664                 case 2:
6665                         result = update_printer(p, r->in.handle,
6666                                                 r->in.info_ctr,
6667                                                 r->in.devmode_ctr->devmode);
6668                         if (!W_ERROR_IS_OK(result))
6669                                 return result;
6670                         if (r->in.secdesc_ctr->sd)
6671                                 result = update_printer_sec(r->in.handle, p,
6672                                                             r->in.secdesc_ctr);
6673                         return result;
6674                 case 3:
6675                         return update_printer_sec(r->in.handle, p,
6676                                                   r->in.secdesc_ctr);
6677                 case 7:
6678                         return publish_or_unpublish_printer(p, r->in.handle,
6679                                                             r->in.info_ctr->info.info7);
6680                 case 8:
6681                         return update_printer_devmode(p, r->in.handle,
6682                                                       r->in.devmode_ctr->devmode);
6683                 default:
6684                         return WERR_UNKNOWN_LEVEL;
6685         }
6686 }
6687
6688 /****************************************************************
6689  _spoolss_FindClosePrinterNotify
6690 ****************************************************************/
6691
6692 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6693                                        struct spoolss_FindClosePrinterNotify *r)
6694 {
6695         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6696
6697         if (!Printer) {
6698                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6699                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6700                 return WERR_BADFID;
6701         }
6702
6703         if (Printer->notify.cli_chan != NULL &&
6704             Printer->notify.cli_chan->active_connections > 0) {
6705                 int snum = -1;
6706
6707                 if (Printer->printer_type == SPLHND_PRINTER) {
6708                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6709                                 return WERR_BADFID;
6710                         }
6711                 }
6712
6713                 srv_spoolss_replycloseprinter(snum, Printer);
6714         }
6715
6716         Printer->notify.flags=0;
6717         Printer->notify.options=0;
6718         Printer->notify.localmachine[0]='\0';
6719         Printer->notify.printerlocal=0;
6720         TALLOC_FREE(Printer->notify.option);
6721
6722         return WERR_OK;
6723 }
6724
6725 /****************************************************************
6726  _spoolss_AddJob
6727 ****************************************************************/
6728
6729 WERROR _spoolss_AddJob(struct pipes_struct *p,
6730                        struct spoolss_AddJob *r)
6731 {
6732         if (!r->in.buffer && (r->in.offered != 0)) {
6733                 return WERR_INVALID_PARAM;
6734         }
6735
6736         /* this is what a NT server returns for AddJob. AddJob must fail on
6737          * non-local printers */
6738
6739         if (r->in.level != 1) {
6740                 return WERR_UNKNOWN_LEVEL;
6741         }
6742
6743         return WERR_INVALID_PARAM;
6744 }
6745
6746 /****************************************************************************
6747 fill_job_info1
6748 ****************************************************************************/
6749
6750 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6751                              struct spoolss_JobInfo1 *r,
6752                              const print_queue_struct *queue,
6753                              int position, int snum,
6754                              struct spoolss_PrinterInfo2 *pinfo2)
6755 {
6756         struct tm *t;
6757
6758         t = gmtime(&queue->time);
6759
6760         r->job_id               = queue->job;
6761
6762         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6763         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6764         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6765         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6766         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6767         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6768         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6769         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6770         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6771         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6772         r->text_status          = talloc_strdup(mem_ctx, "");
6773         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6774
6775         r->status               = nt_printj_status(queue->status);
6776         r->priority             = queue->priority;
6777         r->position             = position;
6778         r->total_pages          = queue->page_count;
6779         r->pages_printed        = 0; /* ??? */
6780
6781         init_systemtime(&r->submitted, t);
6782
6783         return WERR_OK;
6784 }
6785
6786 /****************************************************************************
6787 fill_job_info2
6788 ****************************************************************************/
6789
6790 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6791                              struct spoolss_JobInfo2 *r,
6792                              const print_queue_struct *queue,
6793                              int position, int snum,
6794                              struct spoolss_PrinterInfo2 *pinfo2,
6795                              struct spoolss_DeviceMode *devmode)
6796 {
6797         struct tm *t;
6798
6799         t = gmtime(&queue->time);
6800
6801         r->job_id               = queue->job;
6802
6803         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6804         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6805         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6806         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6807         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6808         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6809         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6810         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6811         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6812         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6813         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6814         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6815         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6816         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6817         r->parameters           = talloc_strdup(mem_ctx, "");
6818         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6819         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6820         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6821
6822         r->devmode              = devmode;
6823
6824         r->text_status          = talloc_strdup(mem_ctx, "");
6825         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6826
6827         r->secdesc              = NULL;
6828
6829         r->status               = nt_printj_status(queue->status);
6830         r->priority             = queue->priority;
6831         r->position             = position;
6832         r->start_time           = 0;
6833         r->until_time           = 0;
6834         r->total_pages          = queue->page_count;
6835         r->size                 = queue->size;
6836         init_systemtime(&r->submitted, t);
6837         r->time                 = 0;
6838         r->pages_printed        = 0; /* ??? */
6839
6840         return WERR_OK;
6841 }
6842
6843 /****************************************************************************
6844 fill_job_info3
6845 ****************************************************************************/
6846
6847 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6848                              struct spoolss_JobInfo3 *r,
6849                              const print_queue_struct *queue,
6850                              const print_queue_struct *next_queue,
6851                              int position, int snum,
6852                              struct spoolss_PrinterInfo2 *pinfo2)
6853 {
6854         r->job_id               = queue->job;
6855         r->next_job_id          = 0;
6856         if (next_queue) {
6857                 r->next_job_id  = next_queue->job;
6858         }
6859         r->reserved             = 0;
6860
6861         return WERR_OK;
6862 }
6863
6864 /****************************************************************************
6865  Enumjobs at level 1.
6866 ****************************************************************************/
6867
6868 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6869                               const print_queue_struct *queue,
6870                               uint32_t num_queues, int snum,
6871                               struct spoolss_PrinterInfo2 *pinfo2,
6872                               union spoolss_JobInfo **info_p,
6873                               uint32_t *count)
6874 {
6875         union spoolss_JobInfo *info;
6876         int i;
6877         WERROR result = WERR_OK;
6878
6879         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6880         W_ERROR_HAVE_NO_MEMORY(info);
6881
6882         *count = num_queues;
6883
6884         for (i=0; i<*count; i++) {
6885                 result = fill_job_info1(info,
6886                                         &info[i].info1,
6887                                         &queue[i],
6888                                         i,
6889                                         snum,
6890                                         pinfo2);
6891                 if (!W_ERROR_IS_OK(result)) {
6892                         goto out;
6893                 }
6894         }
6895
6896  out:
6897         if (!W_ERROR_IS_OK(result)) {
6898                 TALLOC_FREE(info);
6899                 *count = 0;
6900                 return result;
6901         }
6902
6903         *info_p = info;
6904
6905         return WERR_OK;
6906 }
6907
6908 /****************************************************************************
6909  Enumjobs at level 2.
6910 ****************************************************************************/
6911
6912 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6913                               const print_queue_struct *queue,
6914                               uint32_t num_queues, int snum,
6915                               struct spoolss_PrinterInfo2 *pinfo2,
6916                               union spoolss_JobInfo **info_p,
6917                               uint32_t *count)
6918 {
6919         union spoolss_JobInfo *info;
6920         int i;
6921         WERROR result = WERR_OK;
6922
6923         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6924         W_ERROR_HAVE_NO_MEMORY(info);
6925
6926         *count = num_queues;
6927
6928         for (i=0; i<*count; i++) {
6929                 struct spoolss_DeviceMode *devmode;
6930
6931                 result = spoolss_create_default_devmode(info,
6932                                                         pinfo2->printername,
6933                                                         &devmode);
6934                 if (!W_ERROR_IS_OK(result)) {
6935                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6936                         goto out;
6937                 }
6938
6939                 result = fill_job_info2(info,
6940                                         &info[i].info2,
6941                                         &queue[i],
6942                                         i,
6943                                         snum,
6944                                         pinfo2,
6945                                         devmode);
6946                 if (!W_ERROR_IS_OK(result)) {
6947                         goto out;
6948                 }
6949         }
6950
6951  out:
6952         if (!W_ERROR_IS_OK(result)) {
6953                 TALLOC_FREE(info);
6954                 *count = 0;
6955                 return result;
6956         }
6957
6958         *info_p = info;
6959
6960         return WERR_OK;
6961 }
6962
6963 /****************************************************************************
6964  Enumjobs at level 3.
6965 ****************************************************************************/
6966
6967 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6968                               const print_queue_struct *queue,
6969                               uint32_t num_queues, int snum,
6970                               struct spoolss_PrinterInfo2 *pinfo2,
6971                               union spoolss_JobInfo **info_p,
6972                               uint32_t *count)
6973 {
6974         union spoolss_JobInfo *info;
6975         int i;
6976         WERROR result = WERR_OK;
6977
6978         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6979         W_ERROR_HAVE_NO_MEMORY(info);
6980
6981         *count = num_queues;
6982
6983         for (i=0; i<*count; i++) {
6984                 const print_queue_struct *next_queue = NULL;
6985
6986                 if (i+1 < *count) {
6987                         next_queue = &queue[i+1];
6988                 }
6989
6990                 result = fill_job_info3(info,
6991                                         &info[i].info3,
6992                                         &queue[i],
6993                                         next_queue,
6994                                         i,
6995                                         snum,
6996                                         pinfo2);
6997                 if (!W_ERROR_IS_OK(result)) {
6998                         goto out;
6999                 }
7000         }
7001
7002  out:
7003         if (!W_ERROR_IS_OK(result)) {
7004                 TALLOC_FREE(info);
7005                 *count = 0;
7006                 return result;
7007         }
7008
7009         *info_p = info;
7010
7011         return WERR_OK;
7012 }
7013
7014 /****************************************************************
7015  _spoolss_EnumJobs
7016 ****************************************************************/
7017
7018 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7019                          struct spoolss_EnumJobs *r)
7020 {
7021         WERROR result;
7022         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7023         int snum;
7024         print_status_struct prt_status;
7025         print_queue_struct *queue = NULL;
7026         uint32_t count;
7027
7028         /* that's an [in out] buffer */
7029
7030         if (!r->in.buffer && (r->in.offered != 0)) {
7031                 return WERR_INVALID_PARAM;
7032         }
7033
7034         DEBUG(4,("_spoolss_EnumJobs\n"));
7035
7036         *r->out.needed = 0;
7037         *r->out.count = 0;
7038         *r->out.info = NULL;
7039
7040         /* lookup the printer snum and tdb entry */
7041
7042         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7043                 return WERR_BADFID;
7044         }
7045
7046         result = winreg_get_printer(p->mem_ctx,
7047                                     get_session_info_system(),
7048                                     p->msg_ctx,
7049                                     lp_const_servicename(snum),
7050                                     &pinfo2);
7051         if (!W_ERROR_IS_OK(result)) {
7052                 return result;
7053         }
7054
7055         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7056         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7057                 count, prt_status.status, prt_status.message));
7058
7059         if (count == 0) {
7060                 SAFE_FREE(queue);
7061                 TALLOC_FREE(pinfo2);
7062                 return WERR_OK;
7063         }
7064
7065         switch (r->in.level) {
7066         case 1:
7067                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7068                                          pinfo2, r->out.info, r->out.count);
7069                 break;
7070         case 2:
7071                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7072                                          pinfo2, r->out.info, r->out.count);
7073                 break;
7074         case 3:
7075                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7076                                          pinfo2, r->out.info, r->out.count);
7077                 break;
7078         default:
7079                 result = WERR_UNKNOWN_LEVEL;
7080                 break;
7081         }
7082
7083         SAFE_FREE(queue);
7084         TALLOC_FREE(pinfo2);
7085
7086         if (!W_ERROR_IS_OK(result)) {
7087                 return result;
7088         }
7089
7090         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7091                                                      spoolss_EnumJobs,
7092                                                      *r->out.info, r->in.level,
7093                                                      *r->out.count);
7094         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7095         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7096
7097         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7098 }
7099
7100 /****************************************************************
7101  _spoolss_ScheduleJob
7102 ****************************************************************/
7103
7104 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7105                             struct spoolss_ScheduleJob *r)
7106 {
7107         return WERR_OK;
7108 }
7109
7110 /****************************************************************
7111 ****************************************************************/
7112
7113 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7114                                struct messaging_context *msg_ctx,
7115                                const char *printer_name,
7116                                uint32_t job_id,
7117                                struct spoolss_SetJobInfo1 *r)
7118 {
7119         char *old_doc_name;
7120
7121         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7122                 return WERR_BADFID;
7123         }
7124
7125         if (strequal(old_doc_name, r->document_name)) {
7126                 return WERR_OK;
7127         }
7128
7129         if (!print_job_set_name(server_event_context(), msg_ctx,
7130                                 printer_name, job_id, r->document_name)) {
7131                 return WERR_BADFID;
7132         }
7133
7134         return WERR_OK;
7135 }
7136
7137 /****************************************************************
7138  _spoolss_SetJob
7139 ****************************************************************/
7140
7141 WERROR _spoolss_SetJob(struct pipes_struct *p,
7142                        struct spoolss_SetJob *r)
7143 {
7144         const struct auth_serversupplied_info *session_info = p->session_info;
7145         int snum;
7146         WERROR errcode = WERR_BADFUNC;
7147
7148         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7149                 return WERR_BADFID;
7150         }
7151
7152         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7153                 return WERR_INVALID_PRINTER_NAME;
7154         }
7155
7156         switch (r->in.command) {
7157         case SPOOLSS_JOB_CONTROL_CANCEL:
7158         case SPOOLSS_JOB_CONTROL_DELETE:
7159                 errcode = print_job_delete(session_info, p->msg_ctx,
7160                                            snum, r->in.job_id);
7161                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7162                         errcode = WERR_OK;
7163                 }
7164                 break;
7165         case SPOOLSS_JOB_CONTROL_PAUSE:
7166                 if (print_job_pause(session_info, p->msg_ctx,
7167                                     snum, r->in.job_id, &errcode)) {
7168                         errcode = WERR_OK;
7169                 }
7170                 break;
7171         case SPOOLSS_JOB_CONTROL_RESTART:
7172         case SPOOLSS_JOB_CONTROL_RESUME:
7173                 if (print_job_resume(session_info, p->msg_ctx,
7174                                      snum, r->in.job_id, &errcode)) {
7175                         errcode = WERR_OK;
7176                 }
7177                 break;
7178         case 0:
7179                 errcode = WERR_OK;
7180                 break;
7181         default:
7182                 return WERR_UNKNOWN_LEVEL;
7183         }
7184
7185         if (!W_ERROR_IS_OK(errcode)) {
7186                 return errcode;
7187         }
7188
7189         if (r->in.ctr == NULL) {
7190                 return errcode;
7191         }
7192
7193         switch (r->in.ctr->level) {
7194         case 1:
7195                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7196                                            lp_const_servicename(snum),
7197                                            r->in.job_id,
7198                                            r->in.ctr->info.info1);
7199                 break;
7200         case 2:
7201         case 3:
7202         case 4:
7203         default:
7204                 return WERR_UNKNOWN_LEVEL;
7205         }
7206
7207         return errcode;
7208 }
7209
7210 /****************************************************************************
7211  Enumerates all printer drivers by level and architecture.
7212 ****************************************************************************/
7213
7214 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7215                                                        const struct auth_serversupplied_info *session_info,
7216                                                        struct messaging_context *msg_ctx,
7217                                                        const char *servername,
7218                                                        const char *architecture,
7219                                                        uint32_t level,
7220                                                        union spoolss_DriverInfo **info_p,
7221                                                        uint32_t *count_p)
7222 {
7223         int i;
7224         uint32_t version;
7225         struct spoolss_DriverInfo8 *driver;
7226         union spoolss_DriverInfo *info = NULL;
7227         uint32_t count = 0;
7228         WERROR result = WERR_OK;
7229         uint32_t num_drivers;
7230         const char **drivers;
7231
7232         *count_p = 0;
7233         *info_p = NULL;
7234
7235         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7236                 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7237                                                 architecture, version,
7238                                                 &num_drivers, &drivers);
7239                 if (!W_ERROR_IS_OK(result)) {
7240                         goto out;
7241                 }
7242                 DEBUG(4, ("we have:[%d] drivers in environment"
7243                           " [%s] and version [%d]\n",
7244                           num_drivers, architecture, version));
7245
7246                 if (num_drivers != 0) {
7247                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7248                                                     union spoolss_DriverInfo,
7249                                                     count + num_drivers);
7250                         if (!info) {
7251                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7252                                         "failed to enlarge driver info buffer!\n"));
7253                                 result = WERR_NOMEM;
7254                                 goto out;
7255                         }
7256                 }
7257
7258                 for (i = 0; i < num_drivers; i++) {
7259                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7260
7261                         result = winreg_get_driver(mem_ctx, session_info,
7262                                                    msg_ctx,
7263                                                    architecture, drivers[i],
7264                                                    version, &driver);
7265                         if (!W_ERROR_IS_OK(result)) {
7266                                 goto out;
7267                         }
7268
7269                         switch (level) {
7270                         case 1:
7271                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7272                                                                    driver, servername);
7273                                 break;
7274                         case 2:
7275                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7276                                                                    driver, servername);
7277                                 break;
7278                         case 3:
7279                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7280                                                                    driver, servername);
7281                                 break;
7282                         case 4:
7283                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7284                                                                    driver, servername);
7285                                 break;
7286                         case 5:
7287                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7288                                                                    driver, servername);
7289                                 break;
7290                         case 6:
7291                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7292                                                                    driver, servername);
7293                                 break;
7294                         case 8:
7295                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7296                                                                    driver, servername);
7297                                 break;
7298                         default:
7299                                 result = WERR_UNKNOWN_LEVEL;
7300                                 break;
7301                         }
7302
7303                         TALLOC_FREE(driver);
7304
7305                         if (!W_ERROR_IS_OK(result)) {
7306                                 goto out;
7307                         }
7308                 }
7309
7310                 count += num_drivers;
7311                 TALLOC_FREE(drivers);
7312         }
7313
7314  out:
7315         TALLOC_FREE(drivers);
7316
7317         if (!W_ERROR_IS_OK(result)) {
7318                 TALLOC_FREE(info);
7319                 return result;
7320         }
7321
7322         *info_p = info;
7323         *count_p = count;
7324
7325         return WERR_OK;
7326 }
7327
7328 /****************************************************************************
7329  Enumerates all printer drivers by level.
7330 ****************************************************************************/
7331
7332 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7333                                        const struct auth_serversupplied_info *session_info,
7334                                        struct messaging_context *msg_ctx,
7335                                        const char *servername,
7336                                        const char *architecture,
7337                                        uint32_t level,
7338                                        union spoolss_DriverInfo **info_p,
7339                                        uint32_t *count_p)
7340 {
7341         uint32_t a,i;
7342         WERROR result = WERR_OK;
7343
7344         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7345
7346                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7347
7348                         union spoolss_DriverInfo *info = NULL;
7349                         uint32_t count = 0;
7350
7351                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7352                                                                           session_info,
7353                                                                           msg_ctx,
7354                                                                           servername,
7355                                                                           archi_table[a].long_archi,
7356                                                                           level,
7357                                                                           &info,
7358                                                                           &count);
7359                         if (!W_ERROR_IS_OK(result)) {
7360                                 continue;
7361                         }
7362
7363                         for (i=0; i < count; i++) {
7364                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7365                                              info[i], info_p, count_p);
7366                         }
7367                 }
7368
7369                 return result;
7370         }
7371
7372         return enumprinterdrivers_level_by_architecture(mem_ctx,
7373                                                         session_info,
7374                                                         msg_ctx,
7375                                                         servername,
7376                                                         architecture,
7377                                                         level,
7378                                                         info_p,
7379                                                         count_p);
7380 }
7381
7382 /****************************************************************
7383  _spoolss_EnumPrinterDrivers
7384 ****************************************************************/
7385
7386 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7387                                    struct spoolss_EnumPrinterDrivers *r)
7388 {
7389         const char *cservername;
7390         WERROR result;
7391
7392         /* that's an [in out] buffer */
7393
7394         if (!r->in.buffer && (r->in.offered != 0)) {
7395                 return WERR_INVALID_PARAM;
7396         }
7397
7398         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7399
7400         *r->out.needed = 0;
7401         *r->out.count = 0;
7402         *r->out.info = NULL;
7403
7404         cservername = canon_servername(r->in.server);
7405
7406         if (!is_myname_or_ipaddr(cservername)) {
7407                 return WERR_UNKNOWN_PRINTER_DRIVER;
7408         }
7409
7410         result = enumprinterdrivers_level(p->mem_ctx,
7411                                           get_session_info_system(),
7412                                           p->msg_ctx,
7413                                           cservername,
7414                                           r->in.environment,
7415                                           r->in.level,
7416                                           r->out.info,
7417                                           r->out.count);
7418         if (!W_ERROR_IS_OK(result)) {
7419                 return result;
7420         }
7421
7422         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7423                                                      spoolss_EnumPrinterDrivers,
7424                                                      *r->out.info, r->in.level,
7425                                                      *r->out.count);
7426         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7427         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7428
7429         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7430 }
7431
7432 /****************************************************************
7433  _spoolss_EnumForms
7434 ****************************************************************/
7435
7436 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7437                           struct spoolss_EnumForms *r)
7438 {
7439         WERROR result;
7440
7441         *r->out.count = 0;
7442         *r->out.needed = 0;
7443         *r->out.info = NULL;
7444
7445         /* that's an [in out] buffer */
7446
7447         if (!r->in.buffer && (r->in.offered != 0) ) {
7448                 return WERR_INVALID_PARAM;
7449         }
7450
7451         DEBUG(4,("_spoolss_EnumForms\n"));
7452         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7453         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7454
7455         switch (r->in.level) {
7456         case 1:
7457                 result = winreg_printer_enumforms1(p->mem_ctx,
7458                                                    get_session_info_system(),
7459                                                    p->msg_ctx,
7460                                                    r->out.count,
7461                                                    r->out.info);
7462                 break;
7463         default:
7464                 result = WERR_UNKNOWN_LEVEL;
7465                 break;
7466         }
7467
7468         if (!W_ERROR_IS_OK(result)) {
7469                 return result;
7470         }
7471
7472         if (*r->out.count == 0) {
7473                 return WERR_NO_MORE_ITEMS;
7474         }
7475
7476         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7477                                                      spoolss_EnumForms,
7478                                                      *r->out.info, r->in.level,
7479                                                      *r->out.count);
7480         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7481         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7482
7483         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7484 }
7485
7486 /****************************************************************
7487  _spoolss_GetForm
7488 ****************************************************************/
7489
7490 WERROR _spoolss_GetForm(struct pipes_struct *p,
7491                         struct spoolss_GetForm *r)
7492 {
7493         WERROR result;
7494
7495         /* that's an [in out] buffer */
7496
7497         if (!r->in.buffer && (r->in.offered != 0)) {
7498                 return WERR_INVALID_PARAM;
7499         }
7500
7501         DEBUG(4,("_spoolss_GetForm\n"));
7502         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7503         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7504
7505         switch (r->in.level) {
7506         case 1:
7507                 result = winreg_printer_getform1(p->mem_ctx,
7508                                                  get_session_info_system(),
7509                                                  p->msg_ctx,
7510                                                  r->in.form_name,
7511                                                  &r->out.info->info1);
7512                 break;
7513         default:
7514                 result = WERR_UNKNOWN_LEVEL;
7515                 break;
7516         }
7517
7518         if (!W_ERROR_IS_OK(result)) {
7519                 TALLOC_FREE(r->out.info);
7520                 return result;
7521         }
7522
7523         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7524                                                r->out.info, r->in.level);
7525         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7526
7527         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7528 }
7529
7530 /****************************************************************************
7531 ****************************************************************************/
7532
7533 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7534                           struct spoolss_PortInfo1 *r,
7535                           const char *name)
7536 {
7537         r->port_name = talloc_strdup(mem_ctx, name);
7538         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7539
7540         return WERR_OK;
7541 }
7542
7543 /****************************************************************************
7544  TODO: This probably needs distinguish between TCP/IP and Local ports
7545  somehow.
7546 ****************************************************************************/
7547
7548 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7549                           struct spoolss_PortInfo2 *r,
7550                           const char *name)
7551 {
7552         r->port_name = talloc_strdup(mem_ctx, name);
7553         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7554
7555         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7556         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7557
7558         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7559         W_ERROR_HAVE_NO_MEMORY(r->description);
7560
7561         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7562         r->reserved = 0;
7563
7564         return WERR_OK;
7565 }
7566
7567
7568 /****************************************************************************
7569  wrapper around the enumer ports command
7570 ****************************************************************************/
7571
7572 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7573 {
7574         char *cmd = lp_enumports_cmd();
7575         char **qlines = NULL;
7576         char *command = NULL;
7577         int numlines;
7578         int ret;
7579         int fd;
7580
7581         *count = 0;
7582         *lines = NULL;
7583
7584         /* if no hook then just fill in the default port */
7585
7586         if ( !*cmd ) {
7587                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7588                         return WERR_NOMEM;
7589                 }
7590                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7591                         TALLOC_FREE(qlines);
7592                         return WERR_NOMEM;
7593                 }
7594                 qlines[1] = NULL;
7595                 numlines = 1;
7596         }
7597         else {
7598                 /* we have a valid enumport command */
7599
7600                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7601                 if (!command) {
7602                         return WERR_NOMEM;
7603                 }
7604
7605                 DEBUG(10,("Running [%s]\n", command));
7606                 ret = smbrun(command, &fd);
7607                 DEBUG(10,("Returned [%d]\n", ret));
7608                 TALLOC_FREE(command);
7609                 if (ret != 0) {
7610                         if (fd != -1) {
7611                                 close(fd);
7612                         }
7613                         return WERR_ACCESS_DENIED;
7614                 }
7615
7616                 numlines = 0;
7617                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7618                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7619                 close(fd);
7620         }
7621
7622         *count = numlines;
7623         *lines = qlines;
7624
7625         return WERR_OK;
7626 }
7627
7628 /****************************************************************************
7629  enumports level 1.
7630 ****************************************************************************/
7631
7632 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7633                                 union spoolss_PortInfo **info_p,
7634                                 uint32_t *count)
7635 {
7636         union spoolss_PortInfo *info = NULL;
7637         int i=0;
7638         WERROR result = WERR_OK;
7639         char **qlines = NULL;
7640         int numlines = 0;
7641
7642         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7643         if (!W_ERROR_IS_OK(result)) {
7644                 goto out;
7645         }
7646
7647         if (numlines) {
7648                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7649                 if (!info) {
7650                         DEBUG(10,("Returning WERR_NOMEM\n"));
7651                         result = WERR_NOMEM;
7652                         goto out;
7653                 }
7654
7655                 for (i=0; i<numlines; i++) {
7656                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7657                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7658                         if (!W_ERROR_IS_OK(result)) {
7659                                 goto out;
7660                         }
7661                 }
7662         }
7663         TALLOC_FREE(qlines);
7664
7665 out:
7666         if (!W_ERROR_IS_OK(result)) {
7667                 TALLOC_FREE(info);
7668                 TALLOC_FREE(qlines);
7669                 *count = 0;
7670                 *info_p = NULL;
7671                 return result;
7672         }
7673
7674         *info_p = info;
7675         *count = numlines;
7676
7677         return WERR_OK;
7678 }
7679
7680 /****************************************************************************
7681  enumports level 2.
7682 ****************************************************************************/
7683
7684 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7685                                 union spoolss_PortInfo **info_p,
7686                                 uint32_t *count)
7687 {
7688         union spoolss_PortInfo *info = NULL;
7689         int i=0;
7690         WERROR result = WERR_OK;
7691         char **qlines = NULL;
7692         int numlines = 0;
7693
7694         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7695         if (!W_ERROR_IS_OK(result)) {
7696                 goto out;
7697         }
7698
7699         if (numlines) {
7700                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7701                 if (!info) {
7702                         DEBUG(10,("Returning WERR_NOMEM\n"));
7703                         result = WERR_NOMEM;
7704                         goto out;
7705                 }
7706
7707                 for (i=0; i<numlines; i++) {
7708                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7709                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7710                         if (!W_ERROR_IS_OK(result)) {
7711                                 goto out;
7712                         }
7713                 }
7714         }
7715         TALLOC_FREE(qlines);
7716
7717 out:
7718         if (!W_ERROR_IS_OK(result)) {
7719                 TALLOC_FREE(info);
7720                 TALLOC_FREE(qlines);
7721                 *count = 0;
7722                 *info_p = NULL;
7723                 return result;
7724         }
7725
7726         *info_p = info;
7727         *count = numlines;
7728
7729         return WERR_OK;
7730 }
7731
7732 /****************************************************************
7733  _spoolss_EnumPorts
7734 ****************************************************************/
7735
7736 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7737                           struct spoolss_EnumPorts *r)
7738 {
7739         WERROR result;
7740
7741         /* that's an [in out] buffer */
7742
7743         if (!r->in.buffer && (r->in.offered != 0)) {
7744                 return WERR_INVALID_PARAM;
7745         }
7746
7747         DEBUG(4,("_spoolss_EnumPorts\n"));
7748
7749         *r->out.count = 0;
7750         *r->out.needed = 0;
7751         *r->out.info = NULL;
7752
7753         switch (r->in.level) {
7754         case 1:
7755                 result = enumports_level_1(p->mem_ctx, r->out.info,
7756                                            r->out.count);
7757                 break;
7758         case 2:
7759                 result = enumports_level_2(p->mem_ctx, r->out.info,
7760                                            r->out.count);
7761                 break;
7762         default:
7763                 return WERR_UNKNOWN_LEVEL;
7764         }
7765
7766         if (!W_ERROR_IS_OK(result)) {
7767                 return result;
7768         }
7769
7770         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7771                                                      spoolss_EnumPorts,
7772                                                      *r->out.info, r->in.level,
7773                                                      *r->out.count);
7774         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7775         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7776
7777         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7778 }
7779
7780 /****************************************************************************
7781 ****************************************************************************/
7782
7783 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7784                                            const char *server,
7785                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7786                                            struct spoolss_DeviceMode *devmode,
7787                                            struct security_descriptor *secdesc,
7788                                            struct spoolss_UserLevelCtr *user_ctr,
7789                                            struct policy_handle *handle)
7790 {
7791         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7792         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7793         int     snum;
7794         WERROR err = WERR_OK;
7795
7796         /* samba does not have a concept of local, non-shared printers yet, so
7797          * make sure we always setup sharename - gd */
7798         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7799             (info2->printername != NULL && info2->printername[0] != '\0')) {
7800                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7801                         "no sharename has been set, setting printername %s as sharename\n",
7802                         info2->printername));
7803                 info2->sharename = info2->printername;
7804         }
7805
7806         /* check to see if the printer already exists */
7807         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7808                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7809                         info2->sharename));
7810                 return WERR_PRINTER_ALREADY_EXISTS;
7811         }
7812
7813         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7814                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7815                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7816                                 info2->printername));
7817                         return WERR_PRINTER_ALREADY_EXISTS;
7818                 }
7819         }
7820
7821         /* validate printer info struct */
7822         if (!info2->printername || strlen(info2->printername) == 0) {
7823                 return WERR_INVALID_PRINTER_NAME;
7824         }
7825         if (!info2->portname || strlen(info2->portname) == 0) {
7826                 return WERR_UNKNOWN_PORT;
7827         }
7828         if (!info2->drivername || strlen(info2->drivername) == 0) {
7829                 return WERR_UNKNOWN_PRINTER_DRIVER;
7830         }
7831         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7832                 return WERR_UNKNOWN_PRINTPROCESSOR;
7833         }
7834
7835         /* FIXME!!!  smbd should check to see if the driver is installed before
7836            trying to add a printer like this  --jerry */
7837
7838         if (*lp_addprinter_cmd() ) {
7839                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7840                                        info2, p->client_id->addr,
7841                                        p->msg_ctx) ) {
7842                         return WERR_ACCESS_DENIED;
7843                 }
7844         } else {
7845                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7846                         "smb.conf parameter \"addprinter command\" is defined. This"
7847                         "parameter must exist for this call to succeed\n",
7848                         info2->sharename ));
7849         }
7850
7851         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7852                 return WERR_ACCESS_DENIED;
7853         }
7854
7855         /* you must be a printer admin to add a new printer */
7856         if (!print_access_check(p->session_info,
7857                                 p->msg_ctx,
7858                                 snum,
7859                                 PRINTER_ACCESS_ADMINISTER)) {
7860                 return WERR_ACCESS_DENIED;
7861         }
7862
7863         /*
7864          * Do sanity check on the requested changes for Samba.
7865          */
7866
7867         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7868                 return WERR_INVALID_PARAM;
7869         }
7870
7871         if (devmode == NULL) {
7872                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7873         }
7874
7875         update_dsspooler(p->mem_ctx,
7876                          get_session_info_system(),
7877                          p->msg_ctx,
7878                          0,
7879                          info2,
7880                          NULL);
7881
7882         err = winreg_update_printer(p->mem_ctx,
7883                                     get_session_info_system(),
7884                                     p->msg_ctx,
7885                                     info2->sharename,
7886                                     info2_mask,
7887                                     info2,
7888                                     devmode,
7889                                     secdesc);
7890         if (!W_ERROR_IS_OK(err)) {
7891                 return err;
7892         }
7893
7894         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7895         if (!W_ERROR_IS_OK(err)) {
7896                 /* Handle open failed - remove addition. */
7897                 ZERO_STRUCTP(handle);
7898                 return err;
7899         }
7900
7901         return WERR_OK;
7902 }
7903
7904 /****************************************************************
7905  _spoolss_AddPrinterEx
7906 ****************************************************************/
7907
7908 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7909                              struct spoolss_AddPrinterEx *r)
7910 {
7911         switch (r->in.info_ctr->level) {
7912         case 1:
7913                 /* we don't handle yet */
7914                 /* but I know what to do ... */
7915                 return WERR_UNKNOWN_LEVEL;
7916         case 2:
7917                 return spoolss_addprinterex_level_2(p, r->in.server,
7918                                                     r->in.info_ctr,
7919                                                     r->in.devmode_ctr->devmode,
7920                                                     r->in.secdesc_ctr->sd,
7921                                                     r->in.userlevel_ctr,
7922                                                     r->out.handle);
7923         default:
7924                 return WERR_UNKNOWN_LEVEL;
7925         }
7926 }
7927
7928 /****************************************************************
7929  _spoolss_AddPrinter
7930 ****************************************************************/
7931
7932 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7933                            struct spoolss_AddPrinter *r)
7934 {
7935         struct spoolss_AddPrinterEx a;
7936         struct spoolss_UserLevelCtr userlevel_ctr;
7937
7938         ZERO_STRUCT(userlevel_ctr);
7939
7940         userlevel_ctr.level = 1;
7941
7942         a.in.server             = r->in.server;
7943         a.in.info_ctr           = r->in.info_ctr;
7944         a.in.devmode_ctr        = r->in.devmode_ctr;
7945         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7946         a.in.userlevel_ctr      = &userlevel_ctr;
7947         a.out.handle            = r->out.handle;
7948
7949         return _spoolss_AddPrinterEx(p, &a);
7950 }
7951
7952 /****************************************************************
7953  _spoolss_AddPrinterDriverEx
7954 ****************************************************************/
7955
7956 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7957                                    struct spoolss_AddPrinterDriverEx *r)
7958 {
7959         WERROR err = WERR_OK;
7960         const char *driver_name = NULL;
7961         uint32_t version;
7962         const char *fn;
7963
7964         switch (p->opnum) {
7965                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7966                         fn = "_spoolss_AddPrinterDriver";
7967                         break;
7968                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7969                         fn = "_spoolss_AddPrinterDriverEx";
7970                         break;
7971                 default:
7972                         return WERR_INVALID_PARAM;
7973         }
7974
7975         /*
7976          * we only support the semantics of AddPrinterDriver()
7977          * i.e. only copy files that are newer than existing ones
7978          */
7979
7980         if (r->in.flags == 0) {
7981                 return WERR_INVALID_PARAM;
7982         }
7983
7984         if (r->in.flags != APD_COPY_NEW_FILES) {
7985                 return WERR_ACCESS_DENIED;
7986         }
7987
7988         /* FIXME */
7989         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7990                 /* Clever hack from Martin Zielinski <mz@seh.de>
7991                  * to allow downgrade from level 8 (Vista).
7992                  */
7993                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7994                         r->in.info_ctr->level));
7995                 return WERR_UNKNOWN_LEVEL;
7996         }
7997
7998         DEBUG(5,("Cleaning driver's information\n"));
7999         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8000         if (!W_ERROR_IS_OK(err))
8001                 goto done;
8002
8003         DEBUG(5,("Moving driver to final destination\n"));
8004         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
8005                                                               &err)) ) {
8006                 goto done;
8007         }
8008
8009         err = winreg_add_driver(p->mem_ctx,
8010                                 get_session_info_system(),
8011                                 p->msg_ctx,
8012                                 r->in.info_ctr,
8013                                 &driver_name,
8014                                 &version);
8015         if (!W_ERROR_IS_OK(err)) {
8016                 goto done;
8017         }
8018
8019         /*
8020          * I think this is where he DrvUpgradePrinter() hook would be
8021          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8022          * server.  Right now, we just need to send ourselves a message
8023          * to update each printer bound to this driver.   --jerry
8024          */
8025
8026         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8027                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8028                         fn, driver_name));
8029         }
8030
8031 done:
8032         return err;
8033 }
8034
8035 /****************************************************************
8036  _spoolss_AddPrinterDriver
8037 ****************************************************************/
8038
8039 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8040                                  struct spoolss_AddPrinterDriver *r)
8041 {
8042         struct spoolss_AddPrinterDriverEx a;
8043
8044         switch (r->in.info_ctr->level) {
8045         case 2:
8046         case 3:
8047         case 4:
8048         case 5:
8049                 break;
8050         default:
8051                 return WERR_UNKNOWN_LEVEL;
8052         }
8053
8054         a.in.servername         = r->in.servername;
8055         a.in.info_ctr           = r->in.info_ctr;
8056         a.in.flags              = APD_COPY_NEW_FILES;
8057
8058         return _spoolss_AddPrinterDriverEx(p, &a);
8059 }
8060
8061 /****************************************************************************
8062 ****************************************************************************/
8063
8064 struct _spoolss_paths {
8065         int type;
8066         const char *share;
8067         const char *dir;
8068 };
8069
8070 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8071
8072 static const struct _spoolss_paths spoolss_paths[]= {
8073         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8074         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8075 };
8076
8077 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8078                                           const char *servername,
8079                                           const char *environment,
8080                                           int component,
8081                                           char **path)
8082 {
8083         const char *pservername = NULL;
8084         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8085         const char *short_archi;
8086
8087         *path = NULL;
8088
8089         /* environment may be empty */
8090         if (environment && strlen(environment)) {
8091                 long_archi = environment;
8092         }
8093
8094         /* servername may be empty */
8095         if (servername && strlen(servername)) {
8096                 pservername = canon_servername(servername);
8097
8098                 if (!is_myname_or_ipaddr(pservername)) {
8099                         return WERR_INVALID_PARAM;
8100                 }
8101         }
8102
8103         if (!(short_archi = get_short_archi(long_archi))) {
8104                 return WERR_INVALID_ENVIRONMENT;
8105         }
8106
8107         switch (component) {
8108         case SPOOLSS_PRTPROCS_PATH:
8109         case SPOOLSS_DRIVER_PATH:
8110                 if (pservername) {
8111                         *path = talloc_asprintf(mem_ctx,
8112                                         "\\\\%s\\%s\\%s",
8113                                         pservername,
8114                                         spoolss_paths[component].share,
8115                                         short_archi);
8116                 } else {
8117                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8118                                         SPOOLSS_DEFAULT_SERVER_PATH,
8119                                         spoolss_paths[component].dir,
8120                                         short_archi);
8121                 }
8122                 break;
8123         default:
8124                 return WERR_INVALID_PARAM;
8125         }
8126
8127         if (!*path) {
8128                 return WERR_NOMEM;
8129         }
8130
8131         return WERR_OK;
8132 }
8133
8134 /****************************************************************************
8135 ****************************************************************************/
8136
8137 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8138                                           const char *servername,
8139                                           const char *environment,
8140                                           struct spoolss_DriverDirectoryInfo1 *r)
8141 {
8142         WERROR werr;
8143         char *path = NULL;
8144
8145         werr = compose_spoolss_server_path(mem_ctx,
8146                                            servername,
8147                                            environment,
8148                                            SPOOLSS_DRIVER_PATH,
8149                                            &path);
8150         if (!W_ERROR_IS_OK(werr)) {
8151                 return werr;
8152         }
8153
8154         DEBUG(4,("printer driver directory: [%s]\n", path));
8155
8156         r->directory_name = path;
8157
8158         return WERR_OK;
8159 }
8160
8161 /****************************************************************
8162  _spoolss_GetPrinterDriverDirectory
8163 ****************************************************************/
8164
8165 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8166                                           struct spoolss_GetPrinterDriverDirectory *r)
8167 {
8168         WERROR werror;
8169
8170         /* that's an [in out] buffer */
8171
8172         if (!r->in.buffer && (r->in.offered != 0)) {
8173                 return WERR_INVALID_PARAM;
8174         }
8175
8176         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8177                 r->in.level));
8178
8179         *r->out.needed = 0;
8180
8181         /* r->in.level is ignored */
8182
8183         werror = getprinterdriverdir_level_1(p->mem_ctx,
8184                                              r->in.server,
8185                                              r->in.environment,
8186                                              &r->out.info->info1);
8187         if (!W_ERROR_IS_OK(werror)) {
8188                 TALLOC_FREE(r->out.info);
8189                 return werror;
8190         }
8191
8192         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8193                                                r->out.info, r->in.level);
8194         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8195
8196         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8197 }
8198
8199 /****************************************************************
8200  _spoolss_EnumPrinterData
8201 ****************************************************************/
8202
8203 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8204                                 struct spoolss_EnumPrinterData *r)
8205 {
8206         WERROR result;
8207         struct spoolss_EnumPrinterDataEx r2;
8208         uint32_t count;
8209         struct spoolss_PrinterEnumValues *info, *val = NULL;
8210         uint32_t needed;
8211
8212         r2.in.handle    = r->in.handle;
8213         r2.in.key_name  = "PrinterDriverData";
8214         r2.in.offered   = 0;
8215         r2.out.count    = &count;
8216         r2.out.info     = &info;
8217         r2.out.needed   = &needed;
8218
8219         result = _spoolss_EnumPrinterDataEx(p, &r2);
8220         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8221                 r2.in.offered = needed;
8222                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8223         }
8224         if (!W_ERROR_IS_OK(result)) {
8225                 return result;
8226         }
8227
8228         /*
8229          * The NT machine wants to know the biggest size of value and data
8230          *
8231          * cf: MSDN EnumPrinterData remark section
8232          */
8233
8234         if (!r->in.value_offered && !r->in.data_offered) {
8235                 uint32_t biggest_valuesize = 0;
8236                 uint32_t biggest_datasize = 0;
8237                 int i, name_length;
8238
8239                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8240
8241                 for (i=0; i<count; i++) {
8242
8243                         name_length = strlen(info[i].value_name);
8244                         if (strlen(info[i].value_name) > biggest_valuesize) {
8245                                 biggest_valuesize = name_length;
8246                         }
8247
8248                         if (info[i].data_length > biggest_datasize) {
8249                                 biggest_datasize = info[i].data_length;
8250                         }
8251
8252                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8253                                 biggest_datasize));
8254                 }
8255
8256                 /* the value is an UNICODE string but real_value_size is the length
8257                    in bytes including the trailing 0 */
8258
8259                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8260                 *r->out.data_needed  = biggest_datasize;
8261
8262                 DEBUG(6,("final values: [%d], [%d]\n",
8263                         *r->out.value_needed, *r->out.data_needed));
8264
8265                 return WERR_OK;
8266         }
8267
8268         if (r->in.enum_index < count) {
8269                 val = &info[r->in.enum_index];
8270         }
8271
8272         if (val == NULL) {
8273                 /* out_value should default to "" or else NT4 has
8274                    problems unmarshalling the response */
8275
8276                 if (r->in.value_offered) {
8277                         *r->out.value_needed = 1;
8278                         r->out.value_name = talloc_strdup(r, "");
8279                         if (!r->out.value_name) {
8280                                 return WERR_NOMEM;
8281                         }
8282                 } else {
8283                         r->out.value_name = NULL;
8284                         *r->out.value_needed = 0;
8285                 }
8286
8287                 /* the data is counted in bytes */
8288
8289                 *r->out.data_needed = r->in.data_offered;
8290
8291                 result = WERR_NO_MORE_ITEMS;
8292         } else {
8293                 /*
8294                  * the value is:
8295                  * - counted in bytes in the request
8296                  * - counted in UNICODE chars in the max reply
8297                  * - counted in bytes in the real size
8298                  *
8299                  * take a pause *before* coding not *during* coding
8300                  */
8301
8302                 /* name */
8303                 if (r->in.value_offered) {
8304                         r->out.value_name = talloc_strdup(r, val->value_name);
8305                         if (!r->out.value_name) {
8306                                 return WERR_NOMEM;
8307                         }
8308                         *r->out.value_needed = val->value_name_len;
8309                 } else {
8310                         r->out.value_name = NULL;
8311                         *r->out.value_needed = 0;
8312                 }
8313
8314                 /* type */
8315
8316                 *r->out.type = val->type;
8317
8318                 /* data - counted in bytes */
8319
8320                 /*
8321                  * See the section "Dynamically Typed Query Parameters"
8322                  * in MS-RPRN.
8323                  */
8324
8325                 if (r->out.data && val->data && val->data->data &&
8326                                 val->data_length && r->in.data_offered) {
8327                         memcpy(r->out.data, val->data->data,
8328                                 MIN(val->data_length,r->in.data_offered));
8329                 }
8330
8331                 *r->out.data_needed = val->data_length;
8332
8333                 result = WERR_OK;
8334         }
8335
8336         return result;
8337 }
8338
8339 /****************************************************************
8340  _spoolss_SetPrinterData
8341 ****************************************************************/
8342
8343 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8344                                struct spoolss_SetPrinterData *r)
8345 {
8346         struct spoolss_SetPrinterDataEx r2;
8347
8348         r2.in.handle            = r->in.handle;
8349         r2.in.key_name          = "PrinterDriverData";
8350         r2.in.value_name        = r->in.value_name;
8351         r2.in.type              = r->in.type;
8352         r2.in.data              = r->in.data;
8353         r2.in.offered           = r->in.offered;
8354
8355         return _spoolss_SetPrinterDataEx(p, &r2);
8356 }
8357
8358 /****************************************************************
8359  _spoolss_ResetPrinter
8360 ****************************************************************/
8361
8362 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8363                              struct spoolss_ResetPrinter *r)
8364 {
8365         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8366         int             snum;
8367
8368         DEBUG(5,("_spoolss_ResetPrinter\n"));
8369
8370         /*
8371          * All we do is to check to see if the handle and queue is valid.
8372          * This call really doesn't mean anything to us because we only
8373          * support RAW printing.   --jerry
8374          */
8375
8376         if (!Printer) {
8377                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8378                         OUR_HANDLE(r->in.handle)));
8379                 return WERR_BADFID;
8380         }
8381
8382         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8383                 return WERR_BADFID;
8384
8385
8386         /* blindly return success */
8387         return WERR_OK;
8388 }
8389
8390 /****************************************************************
8391  _spoolss_DeletePrinterData
8392 ****************************************************************/
8393
8394 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8395                                   struct spoolss_DeletePrinterData *r)
8396 {
8397         struct spoolss_DeletePrinterDataEx r2;
8398
8399         r2.in.handle            = r->in.handle;
8400         r2.in.key_name          = "PrinterDriverData";
8401         r2.in.value_name        = r->in.value_name;
8402
8403         return _spoolss_DeletePrinterDataEx(p, &r2);
8404 }
8405
8406 /****************************************************************
8407  _spoolss_AddForm
8408 ****************************************************************/
8409
8410 WERROR _spoolss_AddForm(struct pipes_struct *p,
8411                         struct spoolss_AddForm *r)
8412 {
8413         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8414         int snum = -1;
8415         WERROR status = WERR_OK;
8416
8417         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8418
8419         DEBUG(5,("_spoolss_AddForm\n"));
8420
8421         if (!Printer) {
8422                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8423                         OUR_HANDLE(r->in.handle)));
8424                 return WERR_BADFID;
8425         }
8426
8427         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8428            and not a printer admin, then fail */
8429
8430         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8431             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8432             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8433                                           p->session_info->info3->base.domain.string,
8434                                           NULL,
8435                                           p->session_info->security_token,
8436                                           lp_printer_admin(snum))) {
8437                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8438                 return WERR_ACCESS_DENIED;
8439         }
8440
8441         switch (form->flags) {
8442         case SPOOLSS_FORM_USER:
8443         case SPOOLSS_FORM_BUILTIN:
8444         case SPOOLSS_FORM_PRINTER:
8445                 break;
8446         default:
8447                 return WERR_INVALID_PARAM;
8448         }
8449
8450         status = winreg_printer_addform1(p->mem_ctx,
8451                                          get_session_info_system(),
8452                                          p->msg_ctx,
8453                                          form);
8454         if (!W_ERROR_IS_OK(status)) {
8455                 return status;
8456         }
8457
8458         /*
8459          * ChangeID must always be set if this is a printer
8460          */
8461         if (Printer->printer_type == SPLHND_PRINTER) {
8462                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8463                         return WERR_BADFID;
8464                 }
8465
8466                 status = winreg_printer_update_changeid(p->mem_ctx,
8467                                                         get_session_info_system(),
8468                                                         p->msg_ctx,
8469                                                         lp_const_servicename(snum));
8470                 if (!W_ERROR_IS_OK(status)) {
8471                         return status;
8472                 }
8473         }
8474
8475         return status;
8476 }
8477
8478 /****************************************************************
8479  _spoolss_DeleteForm
8480 ****************************************************************/
8481
8482 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8483                            struct spoolss_DeleteForm *r)
8484 {
8485         const char *form_name = r->in.form_name;
8486         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8487         int snum = -1;
8488         WERROR status = WERR_OK;
8489
8490         DEBUG(5,("_spoolss_DeleteForm\n"));
8491
8492         if (!Printer) {
8493                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8494                         OUR_HANDLE(r->in.handle)));
8495                 return WERR_BADFID;
8496         }
8497
8498         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8499             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8500             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8501                                           p->session_info->info3->base.domain.string,
8502                                           NULL,
8503                                           p->session_info->security_token,
8504                                           lp_printer_admin(snum))) {
8505                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8506                 return WERR_ACCESS_DENIED;
8507         }
8508
8509         status = winreg_printer_deleteform1(p->mem_ctx,
8510                                             get_session_info_system(),
8511                                             p->msg_ctx,
8512                                             form_name);
8513         if (!W_ERROR_IS_OK(status)) {
8514                 return status;
8515         }
8516
8517         /*
8518          * ChangeID must always be set if this is a printer
8519          */
8520         if (Printer->printer_type == SPLHND_PRINTER) {
8521                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8522                         return WERR_BADFID;
8523                 }
8524
8525                 status = winreg_printer_update_changeid(p->mem_ctx,
8526                                                         get_session_info_system(),
8527                                                         p->msg_ctx,
8528                                                         lp_const_servicename(snum));
8529                 if (!W_ERROR_IS_OK(status)) {
8530                         return status;
8531                 }
8532         }
8533
8534         return status;
8535 }
8536
8537 /****************************************************************
8538  _spoolss_SetForm
8539 ****************************************************************/
8540
8541 WERROR _spoolss_SetForm(struct pipes_struct *p,
8542                         struct spoolss_SetForm *r)
8543 {
8544         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8545         const char *form_name = r->in.form_name;
8546         int snum = -1;
8547         WERROR status = WERR_OK;
8548
8549         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8550
8551         DEBUG(5,("_spoolss_SetForm\n"));
8552
8553         if (!Printer) {
8554                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8555                         OUR_HANDLE(r->in.handle)));
8556                 return WERR_BADFID;
8557         }
8558
8559         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8560            and not a printer admin, then fail */
8561
8562         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8563              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8564              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8565                                           p->session_info->info3->base.domain.string,
8566                                           NULL,
8567                                           p->session_info->security_token,
8568                                           lp_printer_admin(snum))) {
8569                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8570                 return WERR_ACCESS_DENIED;
8571         }
8572
8573         status = winreg_printer_setform1(p->mem_ctx,
8574                                          get_session_info_system(),
8575                                          p->msg_ctx,
8576                                          form_name,
8577                                          form);
8578         if (!W_ERROR_IS_OK(status)) {
8579                 return status;
8580         }
8581
8582         /*
8583          * ChangeID must always be set if this is a printer
8584          */
8585         if (Printer->printer_type == SPLHND_PRINTER) {
8586                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8587                         return WERR_BADFID;
8588                 }
8589
8590                 status = winreg_printer_update_changeid(p->mem_ctx,
8591                                                         get_session_info_system(),
8592                                                         p->msg_ctx,
8593                                                         lp_const_servicename(snum));
8594                 if (!W_ERROR_IS_OK(status)) {
8595                         return status;
8596                 }
8597         }
8598
8599         return status;
8600 }
8601
8602 /****************************************************************************
8603  fill_print_processor1
8604 ****************************************************************************/
8605
8606 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8607                                     struct spoolss_PrintProcessorInfo1 *r,
8608                                     const char *print_processor_name)
8609 {
8610         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8611         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8612
8613         return WERR_OK;
8614 }
8615
8616 /****************************************************************************
8617  enumprintprocessors level 1.
8618 ****************************************************************************/
8619
8620 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8621                                           union spoolss_PrintProcessorInfo **info_p,
8622                                           uint32_t *count)
8623 {
8624         union spoolss_PrintProcessorInfo *info;
8625         WERROR result;
8626
8627         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8628         W_ERROR_HAVE_NO_MEMORY(info);
8629
8630         *count = 1;
8631
8632         result = fill_print_processor1(info, &info[0].info1, "winprint");
8633         if (!W_ERROR_IS_OK(result)) {
8634                 goto out;
8635         }
8636
8637  out:
8638         if (!W_ERROR_IS_OK(result)) {
8639                 TALLOC_FREE(info);
8640                 *count = 0;
8641                 return result;
8642         }
8643
8644         *info_p = info;
8645
8646         return WERR_OK;
8647 }
8648
8649 /****************************************************************
8650  _spoolss_EnumPrintProcessors
8651 ****************************************************************/
8652
8653 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8654                                     struct spoolss_EnumPrintProcessors *r)
8655 {
8656         WERROR result;
8657
8658         /* that's an [in out] buffer */
8659
8660         if (!r->in.buffer && (r->in.offered != 0)) {
8661                 return WERR_INVALID_PARAM;
8662         }
8663
8664         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8665
8666         /*
8667          * Enumerate the print processors ...
8668          *
8669          * Just reply with "winprint", to keep NT happy
8670          * and I can use my nice printer checker.
8671          */
8672
8673         *r->out.count = 0;
8674         *r->out.needed = 0;
8675         *r->out.info = NULL;
8676
8677         if (!get_short_archi(r->in.environment)) {
8678                 return WERR_INVALID_ENVIRONMENT;
8679         }
8680
8681         switch (r->in.level) {
8682         case 1:
8683                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8684                                                      r->out.count);
8685                 break;
8686         default:
8687                 return WERR_UNKNOWN_LEVEL;
8688         }
8689
8690         if (!W_ERROR_IS_OK(result)) {
8691                 return result;
8692         }
8693
8694         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8695                                                      spoolss_EnumPrintProcessors,
8696                                                      *r->out.info, r->in.level,
8697                                                      *r->out.count);
8698         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8699         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8700
8701         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8702 }
8703
8704 /****************************************************************************
8705  fill_printprocdatatype1
8706 ****************************************************************************/
8707
8708 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8709                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8710                                       const char *name_array)
8711 {
8712         r->name_array = talloc_strdup(mem_ctx, name_array);
8713         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8714
8715         return WERR_OK;
8716 }
8717
8718 /****************************************************************************
8719  enumprintprocdatatypes level 1.
8720 ****************************************************************************/
8721
8722 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8723                                              union spoolss_PrintProcDataTypesInfo **info_p,
8724                                              uint32_t *count)
8725 {
8726         WERROR result;
8727         union spoolss_PrintProcDataTypesInfo *info;
8728
8729         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8730         W_ERROR_HAVE_NO_MEMORY(info);
8731
8732         *count = 1;
8733
8734         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8735         if (!W_ERROR_IS_OK(result)) {
8736                 goto out;
8737         }
8738
8739  out:
8740         if (!W_ERROR_IS_OK(result)) {
8741                 TALLOC_FREE(info);
8742                 *count = 0;
8743                 return result;
8744         }
8745
8746         *info_p = info;
8747
8748         return WERR_OK;
8749 }
8750
8751 /****************************************************************
8752  _spoolss_EnumPrintProcDataTypes
8753 ****************************************************************/
8754
8755 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8756                                        struct spoolss_EnumPrintProcDataTypes *r)
8757 {
8758         WERROR result;
8759
8760         /* that's an [in out] buffer */
8761
8762         if (!r->in.buffer && (r->in.offered != 0)) {
8763                 return WERR_INVALID_PARAM;
8764         }
8765
8766         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8767
8768         *r->out.count = 0;
8769         *r->out.needed = 0;
8770         *r->out.info = NULL;
8771
8772         if (r->in.print_processor_name == NULL ||
8773             !strequal(r->in.print_processor_name, "winprint")) {
8774                 return WERR_UNKNOWN_PRINTPROCESSOR;
8775         }
8776
8777         switch (r->in.level) {
8778         case 1:
8779                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8780                                                         r->out.count);
8781                 break;
8782         default:
8783                 return WERR_UNKNOWN_LEVEL;
8784         }
8785
8786         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8787                                                      spoolss_EnumPrintProcDataTypes,
8788                                                      *r->out.info, r->in.level,
8789                                                      *r->out.count);
8790         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8791         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8792
8793         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8794 }
8795
8796 /****************************************************************************
8797  fill_monitor_1
8798 ****************************************************************************/
8799
8800 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8801                              struct spoolss_MonitorInfo1 *r,
8802                              const char *monitor_name)
8803 {
8804         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8805         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8806
8807         return WERR_OK;
8808 }
8809
8810 /****************************************************************************
8811  fill_monitor_2
8812 ****************************************************************************/
8813
8814 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8815                              struct spoolss_MonitorInfo2 *r,
8816                              const char *monitor_name,
8817                              const char *environment,
8818                              const char *dll_name)
8819 {
8820         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8821         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8822         r->environment                  = talloc_strdup(mem_ctx, environment);
8823         W_ERROR_HAVE_NO_MEMORY(r->environment);
8824         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8825         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8826
8827         return WERR_OK;
8828 }
8829
8830 /****************************************************************************
8831  enumprintmonitors level 1.
8832 ****************************************************************************/
8833
8834 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8835                                         union spoolss_MonitorInfo **info_p,
8836                                         uint32_t *count)
8837 {
8838         union spoolss_MonitorInfo *info;
8839         WERROR result = WERR_OK;
8840
8841         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8842         W_ERROR_HAVE_NO_MEMORY(info);
8843
8844         *count = 2;
8845
8846         result = fill_monitor_1(info, &info[0].info1,
8847                                 SPL_LOCAL_PORT);
8848         if (!W_ERROR_IS_OK(result)) {
8849                 goto out;
8850         }
8851
8852         result = fill_monitor_1(info, &info[1].info1,
8853                                 SPL_TCPIP_PORT);
8854         if (!W_ERROR_IS_OK(result)) {
8855                 goto out;
8856         }
8857
8858 out:
8859         if (!W_ERROR_IS_OK(result)) {
8860                 TALLOC_FREE(info);
8861                 *count = 0;
8862                 return result;
8863         }
8864
8865         *info_p = info;
8866
8867         return WERR_OK;
8868 }
8869
8870 /****************************************************************************
8871  enumprintmonitors level 2.
8872 ****************************************************************************/
8873
8874 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8875                                         union spoolss_MonitorInfo **info_p,
8876                                         uint32_t *count)
8877 {
8878         union spoolss_MonitorInfo *info;
8879         WERROR result = WERR_OK;
8880
8881         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8882         W_ERROR_HAVE_NO_MEMORY(info);
8883
8884         *count = 2;
8885
8886         result = fill_monitor_2(info, &info[0].info2,
8887                                 SPL_LOCAL_PORT,
8888                                 "Windows NT X86", /* FIXME */
8889                                 "localmon.dll");
8890         if (!W_ERROR_IS_OK(result)) {
8891                 goto out;
8892         }
8893
8894         result = fill_monitor_2(info, &info[1].info2,
8895                                 SPL_TCPIP_PORT,
8896                                 "Windows NT X86", /* FIXME */
8897                                 "tcpmon.dll");
8898         if (!W_ERROR_IS_OK(result)) {
8899                 goto out;
8900         }
8901
8902 out:
8903         if (!W_ERROR_IS_OK(result)) {
8904                 TALLOC_FREE(info);
8905                 *count = 0;
8906                 return result;
8907         }
8908
8909         *info_p = info;
8910
8911         return WERR_OK;
8912 }
8913
8914 /****************************************************************
8915  _spoolss_EnumMonitors
8916 ****************************************************************/
8917
8918 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8919                              struct spoolss_EnumMonitors *r)
8920 {
8921         WERROR result;
8922
8923         /* that's an [in out] buffer */
8924
8925         if (!r->in.buffer && (r->in.offered != 0)) {
8926                 return WERR_INVALID_PARAM;
8927         }
8928
8929         DEBUG(5,("_spoolss_EnumMonitors\n"));
8930
8931         /*
8932          * Enumerate the print monitors ...
8933          *
8934          * Just reply with "Local Port", to keep NT happy
8935          * and I can use my nice printer checker.
8936          */
8937
8938         *r->out.count = 0;
8939         *r->out.needed = 0;
8940         *r->out.info = NULL;
8941
8942         switch (r->in.level) {
8943         case 1:
8944                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8945                                                    r->out.count);
8946                 break;
8947         case 2:
8948                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8949                                                    r->out.count);
8950                 break;
8951         default:
8952                 return WERR_UNKNOWN_LEVEL;
8953         }
8954
8955         if (!W_ERROR_IS_OK(result)) {
8956                 return result;
8957         }
8958
8959         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8960                                                      spoolss_EnumMonitors,
8961                                                      *r->out.info, r->in.level,
8962                                                      *r->out.count);
8963         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8964         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8965
8966         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8967 }
8968
8969 /****************************************************************************
8970 ****************************************************************************/
8971
8972 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8973                              const print_queue_struct *queue,
8974                              int count, int snum,
8975                              struct spoolss_PrinterInfo2 *pinfo2,
8976                              uint32_t jobid,
8977                              struct spoolss_JobInfo1 *r)
8978 {
8979         int i = 0;
8980         bool found = false;
8981
8982         for (i=0; i<count; i++) {
8983                 if (queue[i].job == (int)jobid) {
8984                         found = true;
8985                         break;
8986                 }
8987         }
8988
8989         if (found == false) {
8990                 /* NT treats not found as bad param... yet another bad choice */
8991                 return WERR_INVALID_PARAM;
8992         }
8993
8994         return fill_job_info1(mem_ctx,
8995                               r,
8996                               &queue[i],
8997                               i,
8998                               snum,
8999                               pinfo2);
9000 }
9001
9002 /****************************************************************************
9003 ****************************************************************************/
9004
9005 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9006                              const print_queue_struct *queue,
9007                              int count, int snum,
9008                              struct spoolss_PrinterInfo2 *pinfo2,
9009                              uint32_t jobid,
9010                              struct spoolss_JobInfo2 *r)
9011 {
9012         int i = 0;
9013         bool found = false;
9014         struct spoolss_DeviceMode *devmode;
9015         WERROR result;
9016
9017         for (i=0; i<count; i++) {
9018                 if (queue[i].job == (int)jobid) {
9019                         found = true;
9020                         break;
9021                 }
9022         }
9023
9024         if (found == false) {
9025                 /* NT treats not found as bad param... yet another bad
9026                    choice */
9027                 return WERR_INVALID_PARAM;
9028         }
9029
9030         /*
9031          * if the print job does not have a DEVMODE associated with it,
9032          * just use the one for the printer. A NULL devicemode is not
9033          *  a failure condition
9034          */
9035
9036         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9037         if (!devmode) {
9038                 result = spoolss_create_default_devmode(mem_ctx,
9039                                                 pinfo2->printername,
9040                                                 &devmode);
9041                 if (!W_ERROR_IS_OK(result)) {
9042                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9043                         return result;
9044                 }
9045         }
9046
9047         return fill_job_info2(mem_ctx,
9048                               r,
9049                               &queue[i],
9050                               i,
9051                               snum,
9052                               pinfo2,
9053                               devmode);
9054 }
9055
9056 /****************************************************************
9057  _spoolss_GetJob
9058 ****************************************************************/
9059
9060 WERROR _spoolss_GetJob(struct pipes_struct *p,
9061                        struct spoolss_GetJob *r)
9062 {
9063         WERROR result = WERR_OK;
9064         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9065         int snum;
9066         int count;
9067         print_queue_struct      *queue = NULL;
9068         print_status_struct prt_status;
9069
9070         /* that's an [in out] buffer */
9071
9072         if (!r->in.buffer && (r->in.offered != 0)) {
9073                 return WERR_INVALID_PARAM;
9074         }
9075
9076         DEBUG(5,("_spoolss_GetJob\n"));
9077
9078         *r->out.needed = 0;
9079
9080         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9081                 return WERR_BADFID;
9082         }
9083
9084         result = winreg_get_printer(p->mem_ctx,
9085                                     get_session_info_system(),
9086                                     p->msg_ctx,
9087                                     lp_const_servicename(snum),
9088                                     &pinfo2);
9089         if (!W_ERROR_IS_OK(result)) {
9090                 return result;
9091         }
9092
9093         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9094
9095         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9096                      count, prt_status.status, prt_status.message));
9097
9098         switch (r->in.level) {
9099         case 1:
9100                 result = getjob_level_1(p->mem_ctx,
9101                                         queue, count, snum, pinfo2,
9102                                         r->in.job_id, &r->out.info->info1);
9103                 break;
9104         case 2:
9105                 result = getjob_level_2(p->mem_ctx,
9106                                         queue, count, snum, pinfo2,
9107                                         r->in.job_id, &r->out.info->info2);
9108                 break;
9109         default:
9110                 result = WERR_UNKNOWN_LEVEL;
9111                 break;
9112         }
9113
9114         SAFE_FREE(queue);
9115         TALLOC_FREE(pinfo2);
9116
9117         if (!W_ERROR_IS_OK(result)) {
9118                 TALLOC_FREE(r->out.info);
9119                 return result;
9120         }
9121
9122         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9123                                                                                    r->in.level);
9124         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9125
9126         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9127 }
9128
9129 /****************************************************************
9130  _spoolss_GetPrinterDataEx
9131 ****************************************************************/
9132
9133 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9134                                  struct spoolss_GetPrinterDataEx *r)
9135 {
9136
9137         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9138         const char *printer;
9139         int                     snum = 0;
9140         WERROR result = WERR_OK;
9141         DATA_BLOB blob;
9142         enum winreg_Type val_type;
9143         uint8_t *val_data;
9144         uint32_t val_size;
9145
9146
9147         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9148
9149         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9150                 r->in.key_name, r->in.value_name));
9151
9152         /* in case of problem, return some default values */
9153
9154         *r->out.needed  = 0;
9155         *r->out.type    = REG_NONE;
9156
9157         if (!Printer) {
9158                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9159                         OUR_HANDLE(r->in.handle)));
9160                 result = WERR_BADFID;
9161                 goto done;
9162         }
9163
9164         /* Is the handle to a printer or to the server? */
9165
9166         if (Printer->printer_type == SPLHND_SERVER) {
9167
9168                 union spoolss_PrinterData data;
9169
9170                 result = getprinterdata_printer_server(p->mem_ctx,
9171                                                        r->in.value_name,
9172                                                        r->out.type,
9173                                                        &data);
9174                 if (!W_ERROR_IS_OK(result)) {
9175                         return result;
9176                 }
9177
9178                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9179                                                   *r->out.type, &data);
9180                 if (!W_ERROR_IS_OK(result)) {
9181                         return result;
9182                 }
9183
9184                 *r->out.needed = blob.length;
9185
9186                 if (r->in.offered >= *r->out.needed) {
9187                         memcpy(r->out.data, blob.data, blob.length);
9188                 }
9189
9190                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9191         }
9192
9193         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9194                 return WERR_BADFID;
9195         }
9196         printer = lp_const_servicename(snum);
9197
9198         /* check to see if the keyname is valid */
9199         if (!strlen(r->in.key_name)) {
9200                 return WERR_INVALID_PARAM;
9201         }
9202
9203         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9204         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9205             strequal(r->in.value_name, "ChangeId")) {
9206                 *r->out.type = REG_DWORD;
9207                 *r->out.needed = 4;
9208                 if (r->in.offered >= *r->out.needed) {
9209                         uint32_t changeid = 0;
9210
9211                         result = winreg_printer_get_changeid(p->mem_ctx,
9212                                                              get_session_info_system(),
9213                                                              p->msg_ctx,
9214                                                              printer,
9215                                                              &changeid);
9216                         if (!W_ERROR_IS_OK(result)) {
9217                                 return result;
9218                         }
9219
9220                         SIVAL(r->out.data, 0, changeid);
9221                         result = WERR_OK;
9222                 }
9223                 goto done;
9224         }
9225
9226         result = winreg_get_printer_dataex(p->mem_ctx,
9227                                            get_session_info_system(),
9228                                            p->msg_ctx,
9229                                            printer,
9230                                            r->in.key_name,
9231                                            r->in.value_name,
9232                                            &val_type,
9233                                            &val_data,
9234                                            &val_size);
9235         if (!W_ERROR_IS_OK(result)) {
9236                 return result;
9237         }
9238
9239         *r->out.needed = val_size;
9240         *r->out.type = val_type;
9241
9242         if (r->in.offered >= *r->out.needed) {
9243                 memcpy(r->out.data, val_data, val_size);
9244         }
9245
9246  done:
9247         /* retain type when returning WERR_MORE_DATA */
9248         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9249
9250         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9251 }
9252
9253 /****************************************************************
9254  _spoolss_SetPrinterDataEx
9255 ****************************************************************/
9256
9257 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9258                                  struct spoolss_SetPrinterDataEx *r)
9259 {
9260         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9261         int                     snum = 0;
9262         WERROR                  result = WERR_OK;
9263         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9264         char                    *oid_string;
9265
9266         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9267
9268         /* From MSDN documentation of SetPrinterDataEx: pass request to
9269            SetPrinterData if key is "PrinterDriverData" */
9270
9271         if (!Printer) {
9272                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9273                         OUR_HANDLE(r->in.handle)));
9274                 return WERR_BADFID;
9275         }
9276
9277         if (Printer->printer_type == SPLHND_SERVER) {
9278                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9279                         "Not implemented for server handles yet\n"));
9280                 return WERR_INVALID_PARAM;
9281         }
9282
9283         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9284                 return WERR_BADFID;
9285         }
9286
9287         /*
9288          * Access check : NT returns "access denied" if you make a
9289          * SetPrinterData call without the necessary privildge.
9290          * we were originally returning OK if nothing changed
9291          * which made Win2k issue **a lot** of SetPrinterData
9292          * when connecting to a printer  --jerry
9293          */
9294
9295         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9296                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9297                         "change denied by handle access permissions\n"));
9298                 return WERR_ACCESS_DENIED;
9299         }
9300
9301         result = winreg_get_printer(Printer,
9302                                     get_session_info_system(),
9303                                     p->msg_ctx,
9304                                     lp_servicename(snum),
9305                                     &pinfo2);
9306         if (!W_ERROR_IS_OK(result)) {
9307                 return result;
9308         }
9309
9310         /* check for OID in valuename */
9311
9312         oid_string = strchr(r->in.value_name, ',');
9313         if (oid_string) {
9314                 *oid_string = '\0';
9315                 oid_string++;
9316         }
9317
9318         /* save the registry data */
9319
9320         result = winreg_set_printer_dataex(p->mem_ctx,
9321                                            get_session_info_system(),
9322                                            p->msg_ctx,
9323                                            pinfo2->sharename,
9324                                            r->in.key_name,
9325                                            r->in.value_name,
9326                                            r->in.type,
9327                                            r->in.data,
9328                                            r->in.offered);
9329
9330         if (W_ERROR_IS_OK(result)) {
9331                 /* save the OID if one was specified */
9332                 if (oid_string) {
9333                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9334                                 r->in.key_name, SPOOL_OID_KEY);
9335                         if (!str) {
9336                                 result = WERR_NOMEM;
9337                                 goto done;
9338                         }
9339
9340                         /*
9341                          * I'm not checking the status here on purpose.  Don't know
9342                          * if this is right, but I'm returning the status from the
9343                          * previous set_printer_dataex() call.  I have no idea if
9344                          * this is right.    --jerry
9345                          */
9346                         winreg_set_printer_dataex(p->mem_ctx,
9347                                                   get_session_info_system(),
9348                                                   p->msg_ctx,
9349                                                   pinfo2->sharename,
9350                                                   str,
9351                                                   r->in.value_name,
9352                                                   REG_SZ,
9353                                                   (uint8_t *) oid_string,
9354                                                   strlen(oid_string) + 1);
9355                 }
9356
9357                 result = winreg_printer_update_changeid(p->mem_ctx,
9358                                                         get_session_info_system(),
9359                                                         p->msg_ctx,
9360                                                         lp_const_servicename(snum));
9361
9362         }
9363
9364 done:
9365         talloc_free(pinfo2);
9366         return result;
9367 }
9368
9369 /****************************************************************
9370  _spoolss_DeletePrinterDataEx
9371 ****************************************************************/
9372
9373 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9374                                     struct spoolss_DeletePrinterDataEx *r)
9375 {
9376         const char *printer;
9377         int             snum=0;
9378         WERROR          status = WERR_OK;
9379         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9380
9381         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9382
9383         if (!Printer) {
9384                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9385                         "Invalid handle (%s:%u:%u).\n",
9386                         OUR_HANDLE(r->in.handle)));
9387                 return WERR_BADFID;
9388         }
9389
9390         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9391                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9392                         "printer properties change denied by handle\n"));
9393                 return WERR_ACCESS_DENIED;
9394         }
9395
9396         if (!r->in.value_name || !r->in.key_name) {
9397                 return WERR_NOMEM;
9398         }
9399
9400         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9401                 return WERR_BADFID;
9402         }
9403         printer = lp_const_servicename(snum);
9404
9405         status = winreg_delete_printer_dataex(p->mem_ctx,
9406                                               get_session_info_system(),
9407                                               p->msg_ctx,
9408                                               printer,
9409                                               r->in.key_name,
9410                                               r->in.value_name);
9411         if (W_ERROR_IS_OK(status)) {
9412                 status = winreg_printer_update_changeid(p->mem_ctx,
9413                                                         get_session_info_system(),
9414                                                         p->msg_ctx,
9415                                                         printer);
9416         }
9417
9418         return status;
9419 }
9420
9421 /****************************************************************
9422  _spoolss_EnumPrinterKey
9423 ****************************************************************/
9424
9425 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9426                                struct spoolss_EnumPrinterKey *r)
9427 {
9428         uint32_t        num_keys;
9429         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9430         int             snum = 0;
9431         WERROR          result = WERR_BADFILE;
9432         const char **array = NULL;
9433         DATA_BLOB blob;
9434
9435         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9436
9437         if (!Printer) {
9438                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9439                         OUR_HANDLE(r->in.handle)));
9440                 return WERR_BADFID;
9441         }
9442
9443         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9444                 return WERR_BADFID;
9445         }
9446
9447         result = winreg_enum_printer_key(p->mem_ctx,
9448                                          get_session_info_system(),
9449                                          p->msg_ctx,
9450                                          lp_const_servicename(snum),
9451                                          r->in.key_name,
9452                                          &num_keys,
9453                                          &array);
9454         if (!W_ERROR_IS_OK(result)) {
9455                 goto done;
9456         }
9457
9458         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9459                 result = WERR_NOMEM;
9460                 goto done;
9461         }
9462
9463         *r->out._ndr_size = r->in.offered / 2;
9464         *r->out.needed = blob.length;
9465
9466         if (r->in.offered < *r->out.needed) {
9467                 result = WERR_MORE_DATA;
9468         } else {
9469                 result = WERR_OK;
9470                 r->out.key_buffer->string_array = array;
9471         }
9472
9473  done:
9474         if (!W_ERROR_IS_OK(result)) {
9475                 TALLOC_FREE(array);
9476                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9477                         *r->out.needed = 0;
9478                 }
9479         }
9480
9481         return result;
9482 }
9483
9484 /****************************************************************
9485  _spoolss_DeletePrinterKey
9486 ****************************************************************/
9487
9488 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9489                                  struct spoolss_DeletePrinterKey *r)
9490 {
9491         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9492         int                     snum=0;
9493         WERROR                  status;
9494         const char *printer;
9495
9496         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9497
9498         if (!Printer) {
9499                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9500                         OUR_HANDLE(r->in.handle)));
9501                 return WERR_BADFID;
9502         }
9503
9504         /* if keyname == NULL, return error */
9505         if ( !r->in.key_name )
9506                 return WERR_INVALID_PARAM;
9507
9508         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9509                 return WERR_BADFID;
9510         }
9511
9512         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9513                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9514                         "printer properties change denied by handle\n"));
9515                 return WERR_ACCESS_DENIED;
9516         }
9517
9518         printer = lp_const_servicename(snum);
9519
9520         /* delete the key and all subkeys */
9521         status = winreg_delete_printer_key(p->mem_ctx,
9522                                            get_session_info_system(),
9523                                            p->msg_ctx,
9524                                            printer,
9525                                            r->in.key_name);
9526         if (W_ERROR_IS_OK(status)) {
9527                 status = winreg_printer_update_changeid(p->mem_ctx,
9528                                                         get_session_info_system(),
9529                                                         p->msg_ctx,
9530                                                         printer);
9531         }
9532
9533         return status;
9534 }
9535
9536 /****************************************************************
9537  _spoolss_EnumPrinterDataEx
9538 ****************************************************************/
9539
9540 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9541                                   struct spoolss_EnumPrinterDataEx *r)
9542 {
9543         uint32_t        count = 0;
9544         struct spoolss_PrinterEnumValues *info = NULL;
9545         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9546         int             snum;
9547         WERROR          result;
9548
9549         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9550
9551         *r->out.count = 0;
9552         *r->out.needed = 0;
9553         *r->out.info = NULL;
9554
9555         if (!Printer) {
9556                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9557                         OUR_HANDLE(r->in.handle)));
9558                 return WERR_BADFID;
9559         }
9560
9561         /*
9562          * first check for a keyname of NULL or "".  Win2k seems to send
9563          * this a lot and we should send back WERR_INVALID_PARAM
9564          * no need to spend time looking up the printer in this case.
9565          * --jerry
9566          */
9567
9568         if (!strlen(r->in.key_name)) {
9569                 result = WERR_INVALID_PARAM;
9570                 goto done;
9571         }
9572
9573         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9574                 return WERR_BADFID;
9575         }
9576
9577         /* now look for a match on the key name */
9578         result = winreg_enum_printer_dataex(p->mem_ctx,
9579                                             get_session_info_system(),
9580                                             p->msg_ctx,
9581                                             lp_const_servicename(snum),
9582                                             r->in.key_name,
9583                                             &count,
9584                                             &info);
9585         if (!W_ERROR_IS_OK(result)) {
9586                 goto done;
9587         }
9588
9589 #if 0 /* FIXME - gd */
9590         /* housekeeping information in the reply */
9591
9592         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9593          * the hand marshalled container size is a multiple
9594          * of 4 bytes for RPC alignment.
9595          */
9596
9597         if (needed % 4) {
9598                 needed += 4-(needed % 4);
9599         }
9600 #endif
9601         *r->out.count   = count;
9602         *r->out.info    = info;
9603
9604  done:
9605         if (!W_ERROR_IS_OK(result)) {
9606                 return result;
9607         }
9608
9609         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9610                                                spoolss_EnumPrinterDataEx,
9611                                                *r->out.info,
9612                                                *r->out.count);
9613         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9614         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9615
9616         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9617 }
9618
9619 /****************************************************************************
9620 ****************************************************************************/
9621
9622 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9623                                                  const char *servername,
9624                                                  const char *environment,
9625                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9626 {
9627         WERROR werr;
9628         char *path = NULL;
9629
9630         werr = compose_spoolss_server_path(mem_ctx,
9631                                            servername,
9632                                            environment,
9633                                            SPOOLSS_PRTPROCS_PATH,
9634                                            &path);
9635         if (!W_ERROR_IS_OK(werr)) {
9636                 return werr;
9637         }
9638
9639         DEBUG(4,("print processor directory: [%s]\n", path));
9640
9641         r->directory_name = path;
9642
9643         return WERR_OK;
9644 }
9645
9646 /****************************************************************
9647  _spoolss_GetPrintProcessorDirectory
9648 ****************************************************************/
9649
9650 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9651                                            struct spoolss_GetPrintProcessorDirectory *r)
9652 {
9653         WERROR result;
9654         char *prnproc_share = NULL;
9655         bool prnproc_share_exists = false;
9656         int snum;
9657
9658         /* that's an [in out] buffer */
9659
9660         if (!r->in.buffer && (r->in.offered != 0)) {
9661                 return WERR_INVALID_PARAM;
9662         }
9663
9664         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9665                 r->in.level));
9666
9667         *r->out.needed = 0;
9668
9669         /* r->in.level is ignored */
9670
9671         /* We always should reply with a local print processor directory so that
9672          * users are not forced to have a [prnproc$] share on the Samba spoolss
9673          * server, if users decide to do so, lets announce it though - Guenther */
9674
9675         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9676         if (!prnproc_share) {
9677                 return WERR_NOMEM;
9678         }
9679         if (snum != -1) {
9680                 prnproc_share_exists = true;
9681         }
9682
9683         result = getprintprocessordirectory_level_1(p->mem_ctx,
9684                                                     prnproc_share_exists ? r->in.server : NULL,
9685                                                     r->in.environment,
9686                                                     &r->out.info->info1);
9687         if (!W_ERROR_IS_OK(result)) {
9688                 TALLOC_FREE(r->out.info);
9689                 return result;
9690         }
9691
9692         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9693                                                                                    r->out.info, r->in.level);
9694         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9695
9696         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9697 }
9698
9699 /*******************************************************************
9700  ********************************************************************/
9701
9702 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9703                                const char *dllname)
9704 {
9705         enum ndr_err_code ndr_err;
9706         struct spoolss_MonitorUi ui;
9707
9708         ui.dll_name = dllname;
9709
9710         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9711                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9712         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9713                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9714         }
9715         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9716 }
9717
9718 /*******************************************************************
9719  Streams the monitor UI DLL name in UNICODE
9720 *******************************************************************/
9721
9722 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9723                                struct security_token *token, DATA_BLOB *in,
9724                                DATA_BLOB *out, uint32_t *needed)
9725 {
9726         const char *dllname = "tcpmonui.dll";
9727
9728         *needed = (strlen(dllname)+1) * 2;
9729
9730         if (out->length < *needed) {
9731                 return WERR_INSUFFICIENT_BUFFER;
9732         }
9733
9734         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9735                 return WERR_NOMEM;
9736         }
9737
9738         return WERR_OK;
9739 }
9740
9741 /*******************************************************************
9742  ********************************************************************/
9743
9744 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9745                              struct spoolss_PortData1 *port1,
9746                              const DATA_BLOB *buf)
9747 {
9748         enum ndr_err_code ndr_err;
9749         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9750                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9751         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9752                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9753         }
9754         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9755 }
9756
9757 /*******************************************************************
9758  ********************************************************************/
9759
9760 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9761                              struct spoolss_PortData2 *port2,
9762                              const DATA_BLOB *buf)
9763 {
9764         enum ndr_err_code ndr_err;
9765         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9766                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9767         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9768                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9769         }
9770         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9771 }
9772
9773 /*******************************************************************
9774  Create a new TCP/IP port
9775 *******************************************************************/
9776
9777 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9778                              struct security_token *token, DATA_BLOB *in,
9779                              DATA_BLOB *out, uint32_t *needed)
9780 {
9781         struct spoolss_PortData1 port1;
9782         struct spoolss_PortData2 port2;
9783         char *device_uri = NULL;
9784         uint32_t version;
9785
9786         const char *portname;
9787         const char *hostaddress;
9788         const char *queue;
9789         uint32_t port_number;
9790         uint32_t protocol;
9791
9792         /* peek for spoolss_PortData version */
9793
9794         if (!in || (in->length < (128 + 4))) {
9795                 return WERR_GENERAL_FAILURE;
9796         }
9797
9798         version = IVAL(in->data, 128);
9799
9800         switch (version) {
9801                 case 1:
9802                         ZERO_STRUCT(port1);
9803
9804                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9805                                 return WERR_NOMEM;
9806                         }
9807
9808                         portname        = port1.portname;
9809                         hostaddress     = port1.hostaddress;
9810                         queue           = port1.queue;
9811                         protocol        = port1.protocol;
9812                         port_number     = port1.port_number;
9813
9814                         break;
9815                 case 2:
9816                         ZERO_STRUCT(port2);
9817
9818                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9819                                 return WERR_NOMEM;
9820                         }
9821
9822                         portname        = port2.portname;
9823                         hostaddress     = port2.hostaddress;
9824                         queue           = port2.queue;
9825                         protocol        = port2.protocol;
9826                         port_number     = port2.port_number;
9827
9828                         break;
9829                 default:
9830                         DEBUG(1,("xcvtcp_addport: "
9831                                 "unknown version of port_data: %d\n", version));
9832                         return WERR_UNKNOWN_PORT;
9833         }
9834
9835         /* create the device URI and call the add_port_hook() */
9836
9837         switch (protocol) {
9838         case PROTOCOL_RAWTCP_TYPE:
9839                 device_uri = talloc_asprintf(mem_ctx,
9840                                 "socket://%s:%d/", hostaddress,
9841                                 port_number);
9842                 break;
9843
9844         case PROTOCOL_LPR_TYPE:
9845                 device_uri = talloc_asprintf(mem_ctx,
9846                         "lpr://%s/%s", hostaddress, queue );
9847                 break;
9848
9849         default:
9850                 return WERR_UNKNOWN_PORT;
9851         }
9852
9853         if (!device_uri) {
9854                 return WERR_NOMEM;
9855         }
9856
9857         return add_port_hook(mem_ctx, token, portname, device_uri);
9858 }
9859
9860 /*******************************************************************
9861 *******************************************************************/
9862
9863 struct xcv_api_table xcvtcp_cmds[] = {
9864         { "MonitorUI",  xcvtcp_monitorui },
9865         { "AddPort",    xcvtcp_addport},
9866         { NULL,         NULL }
9867 };
9868
9869 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9870                                      struct security_token *token, const char *command,
9871                                      DATA_BLOB *inbuf,
9872                                      DATA_BLOB *outbuf,
9873                                      uint32_t *needed )
9874 {
9875         int i;
9876
9877         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9878
9879         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9880                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9881                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9882         }
9883
9884         return WERR_BADFUNC;
9885 }
9886
9887 /*******************************************************************
9888 *******************************************************************/
9889 #if 0   /* don't support management using the "Local Port" monitor */
9890
9891 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9892                                  struct security_token *token, DATA_BLOB *in,
9893                                  DATA_BLOB *out, uint32_t *needed)
9894 {
9895         const char *dllname = "localui.dll";
9896
9897         *needed = (strlen(dllname)+1) * 2;
9898
9899         if (out->length < *needed) {
9900                 return WERR_INSUFFICIENT_BUFFER;
9901         }
9902
9903         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9904                 return WERR_NOMEM;
9905         }
9906
9907         return WERR_OK;
9908 }
9909
9910 /*******************************************************************
9911 *******************************************************************/
9912
9913 struct xcv_api_table xcvlocal_cmds[] = {
9914         { "MonitorUI",  xcvlocal_monitorui },
9915         { NULL,         NULL }
9916 };
9917 #else
9918 struct xcv_api_table xcvlocal_cmds[] = {
9919         { NULL,         NULL }
9920 };
9921 #endif
9922
9923
9924
9925 /*******************************************************************
9926 *******************************************************************/
9927
9928 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9929                                        struct security_token *token, const char *command,
9930                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9931                                        uint32_t *needed)
9932 {
9933         int i;
9934
9935         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9936
9937         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9938                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9939                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9940         }
9941         return WERR_BADFUNC;
9942 }
9943
9944 /****************************************************************
9945  _spoolss_XcvData
9946 ****************************************************************/
9947
9948 WERROR _spoolss_XcvData(struct pipes_struct *p,
9949                         struct spoolss_XcvData *r)
9950 {
9951         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9952         DATA_BLOB out_data = data_blob_null;
9953         WERROR werror;
9954
9955         if (!Printer) {
9956                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9957                         OUR_HANDLE(r->in.handle)));
9958                 return WERR_BADFID;
9959         }
9960
9961         /* Has to be a handle to the TCP/IP port monitor */
9962
9963         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9964                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9965                 return WERR_BADFID;
9966         }
9967
9968         /* requires administrative access to the server */
9969
9970         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9971                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9972                 return WERR_ACCESS_DENIED;
9973         }
9974
9975         /* Allocate the outgoing buffer */
9976
9977         if (r->in.out_data_size) {
9978                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9979                 if (out_data.data == NULL) {
9980                         return WERR_NOMEM;
9981                 }
9982         }
9983
9984         switch ( Printer->printer_type ) {
9985         case SPLHND_PORTMON_TCP:
9986                 werror = process_xcvtcp_command(p->mem_ctx,
9987                                                 p->session_info->security_token,
9988                                                 r->in.function_name,
9989                                                 &r->in.in_data, &out_data,
9990                                                 r->out.needed);
9991                 break;
9992         case SPLHND_PORTMON_LOCAL:
9993                 werror = process_xcvlocal_command(p->mem_ctx,
9994                                                   p->session_info->security_token,
9995                                                   r->in.function_name,
9996                                                   &r->in.in_data, &out_data,
9997                                                   r->out.needed);
9998                 break;
9999         default:
10000                 werror = WERR_INVALID_PRINT_MONITOR;
10001         }
10002
10003         if (!W_ERROR_IS_OK(werror)) {
10004                 return werror;
10005         }
10006
10007         *r->out.status_code = 0;
10008
10009         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10010                 memcpy(r->out.out_data, out_data.data,
10011                         MIN(r->in.out_data_size, out_data.length));
10012         }
10013
10014         return WERR_OK;
10015 }
10016
10017 /****************************************************************
10018  _spoolss_AddPrintProcessor
10019 ****************************************************************/
10020
10021 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10022                                   struct spoolss_AddPrintProcessor *r)
10023 {
10024         /* for now, just indicate success and ignore the add.  We'll
10025            automatically set the winprint processor for printer
10026            entries later.  Used to debug the LexMark Optra S 1855 PCL
10027            driver --jerry */
10028
10029         return WERR_OK;
10030 }
10031
10032 /****************************************************************
10033  _spoolss_AddPort
10034 ****************************************************************/
10035
10036 WERROR _spoolss_AddPort(struct pipes_struct *p,
10037                         struct spoolss_AddPort *r)
10038 {
10039         /* do what w2k3 does */
10040
10041         return WERR_NOT_SUPPORTED;
10042 }
10043
10044 /****************************************************************
10045  _spoolss_GetPrinterDriver
10046 ****************************************************************/
10047
10048 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10049                                  struct spoolss_GetPrinterDriver *r)
10050 {
10051         p->rng_fault_state = true;
10052         return WERR_NOT_SUPPORTED;
10053 }
10054
10055 /****************************************************************
10056  _spoolss_ReadPrinter
10057 ****************************************************************/
10058
10059 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10060                             struct spoolss_ReadPrinter *r)
10061 {
10062         p->rng_fault_state = true;
10063         return WERR_NOT_SUPPORTED;
10064 }
10065
10066 /****************************************************************
10067  _spoolss_WaitForPrinterChange
10068 ****************************************************************/
10069
10070 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10071                                      struct spoolss_WaitForPrinterChange *r)
10072 {
10073         p->rng_fault_state = true;
10074         return WERR_NOT_SUPPORTED;
10075 }
10076
10077 /****************************************************************
10078  _spoolss_ConfigurePort
10079 ****************************************************************/
10080
10081 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10082                               struct spoolss_ConfigurePort *r)
10083 {
10084         p->rng_fault_state = true;
10085         return WERR_NOT_SUPPORTED;
10086 }
10087
10088 /****************************************************************
10089  _spoolss_DeletePort
10090 ****************************************************************/
10091
10092 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10093                            struct spoolss_DeletePort *r)
10094 {
10095         p->rng_fault_state = true;
10096         return WERR_NOT_SUPPORTED;
10097 }
10098
10099 /****************************************************************
10100  _spoolss_CreatePrinterIC
10101 ****************************************************************/
10102
10103 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10104                                 struct spoolss_CreatePrinterIC *r)
10105 {
10106         p->rng_fault_state = true;
10107         return WERR_NOT_SUPPORTED;
10108 }
10109
10110 /****************************************************************
10111  _spoolss_PlayGDIScriptOnPrinterIC
10112 ****************************************************************/
10113
10114 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10115                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10116 {
10117         p->rng_fault_state = true;
10118         return WERR_NOT_SUPPORTED;
10119 }
10120
10121 /****************************************************************
10122  _spoolss_DeletePrinterIC
10123 ****************************************************************/
10124
10125 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10126                                 struct spoolss_DeletePrinterIC *r)
10127 {
10128         p->rng_fault_state = true;
10129         return WERR_NOT_SUPPORTED;
10130 }
10131
10132 /****************************************************************
10133  _spoolss_AddPrinterConnection
10134 ****************************************************************/
10135
10136 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10137                                      struct spoolss_AddPrinterConnection *r)
10138 {
10139         p->rng_fault_state = true;
10140         return WERR_NOT_SUPPORTED;
10141 }
10142
10143 /****************************************************************
10144  _spoolss_DeletePrinterConnection
10145 ****************************************************************/
10146
10147 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10148                                         struct spoolss_DeletePrinterConnection *r)
10149 {
10150         p->rng_fault_state = true;
10151         return WERR_NOT_SUPPORTED;
10152 }
10153
10154 /****************************************************************
10155  _spoolss_PrinterMessageBox
10156 ****************************************************************/
10157
10158 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10159                                   struct spoolss_PrinterMessageBox *r)
10160 {
10161         p->rng_fault_state = true;
10162         return WERR_NOT_SUPPORTED;
10163 }
10164
10165 /****************************************************************
10166  _spoolss_AddMonitor
10167 ****************************************************************/
10168
10169 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10170                            struct spoolss_AddMonitor *r)
10171 {
10172         p->rng_fault_state = true;
10173         return WERR_NOT_SUPPORTED;
10174 }
10175
10176 /****************************************************************
10177  _spoolss_DeleteMonitor
10178 ****************************************************************/
10179
10180 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10181                               struct spoolss_DeleteMonitor *r)
10182 {
10183         p->rng_fault_state = true;
10184         return WERR_NOT_SUPPORTED;
10185 }
10186
10187 /****************************************************************
10188  _spoolss_DeletePrintProcessor
10189 ****************************************************************/
10190
10191 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10192                                      struct spoolss_DeletePrintProcessor *r)
10193 {
10194         p->rng_fault_state = true;
10195         return WERR_NOT_SUPPORTED;
10196 }
10197
10198 /****************************************************************
10199  _spoolss_AddPrintProvidor
10200 ****************************************************************/
10201
10202 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10203                                  struct spoolss_AddPrintProvidor *r)
10204 {
10205         p->rng_fault_state = true;
10206         return WERR_NOT_SUPPORTED;
10207 }
10208
10209 /****************************************************************
10210  _spoolss_DeletePrintProvidor
10211 ****************************************************************/
10212
10213 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10214                                     struct spoolss_DeletePrintProvidor *r)
10215 {
10216         p->rng_fault_state = true;
10217         return WERR_NOT_SUPPORTED;
10218 }
10219
10220 /****************************************************************
10221  _spoolss_FindFirstPrinterChangeNotification
10222 ****************************************************************/
10223
10224 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10225                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10226 {
10227         p->rng_fault_state = true;
10228         return WERR_NOT_SUPPORTED;
10229 }
10230
10231 /****************************************************************
10232  _spoolss_FindNextPrinterChangeNotification
10233 ****************************************************************/
10234
10235 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10236                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10237 {
10238         p->rng_fault_state = true;
10239         return WERR_NOT_SUPPORTED;
10240 }
10241
10242 /****************************************************************
10243  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10244 ****************************************************************/
10245
10246 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10247                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10248 {
10249         p->rng_fault_state = true;
10250         return WERR_NOT_SUPPORTED;
10251 }
10252
10253 /****************************************************************
10254  _spoolss_ReplyOpenPrinter
10255 ****************************************************************/
10256
10257 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10258                                  struct spoolss_ReplyOpenPrinter *r)
10259 {
10260         p->rng_fault_state = true;
10261         return WERR_NOT_SUPPORTED;
10262 }
10263
10264 /****************************************************************
10265  _spoolss_RouterReplyPrinter
10266 ****************************************************************/
10267
10268 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10269                                    struct spoolss_RouterReplyPrinter *r)
10270 {
10271         p->rng_fault_state = true;
10272         return WERR_NOT_SUPPORTED;
10273 }
10274
10275 /****************************************************************
10276  _spoolss_ReplyClosePrinter
10277 ****************************************************************/
10278
10279 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10280                                   struct spoolss_ReplyClosePrinter *r)
10281 {
10282         p->rng_fault_state = true;
10283         return WERR_NOT_SUPPORTED;
10284 }
10285
10286 /****************************************************************
10287  _spoolss_AddPortEx
10288 ****************************************************************/
10289
10290 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10291                           struct spoolss_AddPortEx *r)
10292 {
10293         p->rng_fault_state = true;
10294         return WERR_NOT_SUPPORTED;
10295 }
10296
10297 /****************************************************************
10298  _spoolss_RouterFindFirstPrinterChangeNotification
10299 ****************************************************************/
10300
10301 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10302                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10303 {
10304         p->rng_fault_state = true;
10305         return WERR_NOT_SUPPORTED;
10306 }
10307
10308 /****************************************************************
10309  _spoolss_SpoolerInit
10310 ****************************************************************/
10311
10312 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10313                             struct spoolss_SpoolerInit *r)
10314 {
10315         p->rng_fault_state = true;
10316         return WERR_NOT_SUPPORTED;
10317 }
10318
10319 /****************************************************************
10320  _spoolss_ResetPrinterEx
10321 ****************************************************************/
10322
10323 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10324                                struct spoolss_ResetPrinterEx *r)
10325 {
10326         p->rng_fault_state = true;
10327         return WERR_NOT_SUPPORTED;
10328 }
10329
10330 /****************************************************************
10331  _spoolss_RouterReplyPrinterEx
10332 ****************************************************************/
10333
10334 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10335                                      struct spoolss_RouterReplyPrinterEx *r)
10336 {
10337         p->rng_fault_state = true;
10338         return WERR_NOT_SUPPORTED;
10339 }
10340
10341 /****************************************************************
10342  _spoolss_44
10343 ****************************************************************/
10344
10345 WERROR _spoolss_44(struct pipes_struct *p,
10346                    struct spoolss_44 *r)
10347 {
10348         p->rng_fault_state = true;
10349         return WERR_NOT_SUPPORTED;
10350 }
10351
10352 /****************************************************************
10353  _spoolss_SetPort
10354 ****************************************************************/
10355
10356 WERROR _spoolss_SetPort(struct pipes_struct *p,
10357                         struct spoolss_SetPort *r)
10358 {
10359         p->rng_fault_state = true;
10360         return WERR_NOT_SUPPORTED;
10361 }
10362
10363 /****************************************************************
10364  _spoolss_4a
10365 ****************************************************************/
10366
10367 WERROR _spoolss_4a(struct pipes_struct *p,
10368                    struct spoolss_4a *r)
10369 {
10370         p->rng_fault_state = true;
10371         return WERR_NOT_SUPPORTED;
10372 }
10373
10374 /****************************************************************
10375  _spoolss_4b
10376 ****************************************************************/
10377
10378 WERROR _spoolss_4b(struct pipes_struct *p,
10379                    struct spoolss_4b *r)
10380 {
10381         p->rng_fault_state = true;
10382         return WERR_NOT_SUPPORTED;
10383 }
10384
10385 /****************************************************************
10386  _spoolss_4c
10387 ****************************************************************/
10388
10389 WERROR _spoolss_4c(struct pipes_struct *p,
10390                    struct spoolss_4c *r)
10391 {
10392         p->rng_fault_state = true;
10393         return WERR_NOT_SUPPORTED;
10394 }
10395
10396 /****************************************************************
10397  _spoolss_53
10398 ****************************************************************/
10399
10400 WERROR _spoolss_53(struct pipes_struct *p,
10401                    struct spoolss_53 *r)
10402 {
10403         p->rng_fault_state = true;
10404         return WERR_NOT_SUPPORTED;
10405 }
10406
10407 /****************************************************************
10408  _spoolss_AddPerMachineConnection
10409 ****************************************************************/
10410
10411 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10412                                         struct spoolss_AddPerMachineConnection *r)
10413 {
10414         p->rng_fault_state = true;
10415         return WERR_NOT_SUPPORTED;
10416 }
10417
10418 /****************************************************************
10419  _spoolss_DeletePerMachineConnection
10420 ****************************************************************/
10421
10422 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10423                                            struct spoolss_DeletePerMachineConnection *r)
10424 {
10425         p->rng_fault_state = true;
10426         return WERR_NOT_SUPPORTED;
10427 }
10428
10429 /****************************************************************
10430  _spoolss_EnumPerMachineConnections
10431 ****************************************************************/
10432
10433 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10434                                           struct spoolss_EnumPerMachineConnections *r)
10435 {
10436         p->rng_fault_state = true;
10437         return WERR_NOT_SUPPORTED;
10438 }
10439
10440 /****************************************************************
10441  _spoolss_5a
10442 ****************************************************************/
10443
10444 WERROR _spoolss_5a(struct pipes_struct *p,
10445                    struct spoolss_5a *r)
10446 {
10447         p->rng_fault_state = true;
10448         return WERR_NOT_SUPPORTED;
10449 }
10450
10451 /****************************************************************
10452  _spoolss_5b
10453 ****************************************************************/
10454
10455 WERROR _spoolss_5b(struct pipes_struct *p,
10456                    struct spoolss_5b *r)
10457 {
10458         p->rng_fault_state = true;
10459         return WERR_NOT_SUPPORTED;
10460 }
10461
10462 /****************************************************************
10463  _spoolss_5c
10464 ****************************************************************/
10465
10466 WERROR _spoolss_5c(struct pipes_struct *p,
10467                    struct spoolss_5c *r)
10468 {
10469         p->rng_fault_state = true;
10470         return WERR_NOT_SUPPORTED;
10471 }
10472
10473 /****************************************************************
10474  _spoolss_5d
10475 ****************************************************************/
10476
10477 WERROR _spoolss_5d(struct pipes_struct *p,
10478                    struct spoolss_5d *r)
10479 {
10480         p->rng_fault_state = true;
10481         return WERR_NOT_SUPPORTED;
10482 }
10483
10484 /****************************************************************
10485  _spoolss_5e
10486 ****************************************************************/
10487
10488 WERROR _spoolss_5e(struct pipes_struct *p,
10489                    struct spoolss_5e *r)
10490 {
10491         p->rng_fault_state = true;
10492         return WERR_NOT_SUPPORTED;
10493 }
10494
10495 /****************************************************************
10496  _spoolss_5f
10497 ****************************************************************/
10498
10499 WERROR _spoolss_5f(struct pipes_struct *p,
10500                    struct spoolss_5f *r)
10501 {
10502         p->rng_fault_state = true;
10503         return WERR_NOT_SUPPORTED;
10504 }
10505
10506 /****************************************************************
10507  _spoolss_60
10508 ****************************************************************/
10509
10510 WERROR _spoolss_60(struct pipes_struct *p,
10511                    struct spoolss_60 *r)
10512 {
10513         p->rng_fault_state = true;
10514         return WERR_NOT_SUPPORTED;
10515 }
10516
10517 /****************************************************************
10518  _spoolss_61
10519 ****************************************************************/
10520
10521 WERROR _spoolss_61(struct pipes_struct *p,
10522                    struct spoolss_61 *r)
10523 {
10524         p->rng_fault_state = true;
10525         return WERR_NOT_SUPPORTED;
10526 }
10527
10528 /****************************************************************
10529  _spoolss_62
10530 ****************************************************************/
10531
10532 WERROR _spoolss_62(struct pipes_struct *p,
10533                    struct spoolss_62 *r)
10534 {
10535         p->rng_fault_state = true;
10536         return WERR_NOT_SUPPORTED;
10537 }
10538
10539 /****************************************************************
10540  _spoolss_63
10541 ****************************************************************/
10542
10543 WERROR _spoolss_63(struct pipes_struct *p,
10544                    struct spoolss_63 *r)
10545 {
10546         p->rng_fault_state = true;
10547         return WERR_NOT_SUPPORTED;
10548 }
10549
10550 /****************************************************************
10551  _spoolss_64
10552 ****************************************************************/
10553
10554 WERROR _spoolss_64(struct pipes_struct *p,
10555                    struct spoolss_64 *r)
10556 {
10557         p->rng_fault_state = true;
10558         return WERR_NOT_SUPPORTED;
10559 }
10560
10561 /****************************************************************
10562  _spoolss_65
10563 ****************************************************************/
10564
10565 WERROR _spoolss_65(struct pipes_struct *p,
10566                    struct spoolss_65 *r)
10567 {
10568         p->rng_fault_state = true;
10569         return WERR_NOT_SUPPORTED;
10570 }
10571
10572 /****************************************************************
10573  _spoolss_GetCorePrinterDrivers
10574 ****************************************************************/
10575
10576 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10577                                       struct spoolss_GetCorePrinterDrivers *r)
10578 {
10579         p->rng_fault_state = true;
10580         return WERR_NOT_SUPPORTED;
10581 }
10582
10583 /****************************************************************
10584  _spoolss_67
10585 ****************************************************************/
10586
10587 WERROR _spoolss_67(struct pipes_struct *p,
10588                    struct spoolss_67 *r)
10589 {
10590         p->rng_fault_state = true;
10591         return WERR_NOT_SUPPORTED;
10592 }
10593
10594 /****************************************************************
10595  _spoolss_GetPrinterDriverPackagePath
10596 ****************************************************************/
10597
10598 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10599                                             struct spoolss_GetPrinterDriverPackagePath *r)
10600 {
10601         p->rng_fault_state = true;
10602         return WERR_NOT_SUPPORTED;
10603 }
10604
10605 /****************************************************************
10606  _spoolss_69
10607 ****************************************************************/
10608
10609 WERROR _spoolss_69(struct pipes_struct *p,
10610                    struct spoolss_69 *r)
10611 {
10612         p->rng_fault_state = true;
10613         return WERR_NOT_SUPPORTED;
10614 }
10615
10616 /****************************************************************
10617  _spoolss_6a
10618 ****************************************************************/
10619
10620 WERROR _spoolss_6a(struct pipes_struct *p,
10621                    struct spoolss_6a *r)
10622 {
10623         p->rng_fault_state = true;
10624         return WERR_NOT_SUPPORTED;
10625 }
10626
10627 /****************************************************************
10628  _spoolss_6b
10629 ****************************************************************/
10630
10631 WERROR _spoolss_6b(struct pipes_struct *p,
10632                    struct spoolss_6b *r)
10633 {
10634         p->rng_fault_state = true;
10635         return WERR_NOT_SUPPORTED;
10636 }
10637
10638 /****************************************************************
10639  _spoolss_6c
10640 ****************************************************************/
10641
10642 WERROR _spoolss_6c(struct pipes_struct *p,
10643                    struct spoolss_6c *r)
10644 {
10645         p->rng_fault_state = true;
10646         return WERR_NOT_SUPPORTED;
10647 }
10648
10649 /****************************************************************
10650  _spoolss_6d
10651 ****************************************************************/
10652
10653 WERROR _spoolss_6d(struct pipes_struct *p,
10654                    struct spoolss_6d *r)
10655 {
10656         p->rng_fault_state = true;
10657         return WERR_NOT_SUPPORTED;
10658 }