Try and fix bug #8384 - Windows XP clients seem to crash smbd process every once...
[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 "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "registry/reg_objects.h"
42 #include "include/printing.h"
43 #include "secrets.h"
44 #include "../librpc/gen_ndr/netlogon.h"
45 #include "rpc_misc.h"
46 #include "printing/notify.h"
47 #include "serverid.h"
48 #include "../libcli/registry/util_reg.h"
49 #include "smbd/smbd.h"
50 #include "smbd/globals.h"
51 #include "auth.h"
52 #include "messages.h"
53 #include "rpc_server/spoolss/srv_spoolss_nt.h"
54 #include "util_tdb.h"
55 #include "libsmb/libsmb.h"
56 #include "printing/printer_list.h"
57 #include "../lib/tsocket/tsocket.h"
58 #include "rpc_client/cli_winreg_spoolss.h"
59
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62         ((info)?ndr_size_##fn(info, level, 0):0)
63
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
66
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
69
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71
72 #undef DBGC_CLASS
73 #define DBGC_CLASS DBGC_RPC_SRV
74
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
77 #endif
78
79 struct notify_back_channel;
80
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86         struct printer_handle *prev, *next;
87         bool document_started;
88         bool page_started;
89         uint32 jobid; /* jobid in printing backend */
90         int printer_type;
91         const char *servername;
92         fstring sharename;
93         uint32 type;
94         uint32 access_granted;
95         struct {
96                 uint32 flags;
97                 uint32 options;
98                 fstring localmachine;
99                 uint32 printerlocal;
100                 struct spoolss_NotifyOption *option;
101                 struct policy_handle cli_hnd;
102                 struct notify_back_channel *cli_chan;
103                 uint32 change;
104                 /* are we in a FindNextPrinterChangeNotify() call? */
105                 bool fnpcn;
106                 struct messaging_context *msg_ctx;
107         } notify;
108         struct {
109                 fstring machine;
110                 fstring user;
111         } client;
112
113         /* devmode sent in the OpenPrinter() call */
114         struct spoolss_DeviceMode *devmode;
115
116         /* TODO cache the printer info2 structure */
117         struct spoolss_PrinterInfo2 *info2;
118
119 };
120
121 static struct printer_handle *printers_list;
122
123 struct printer_session_counter {
124         struct printer_session_counter *next;
125         struct printer_session_counter *prev;
126
127         int snum;
128         uint32_t counter;
129 };
130
131 static struct printer_session_counter *counter_list;
132
133 struct notify_back_channel {
134         struct notify_back_channel *prev, *next;
135
136         /* associated client */
137         struct sockaddr_storage client_address;
138
139         /* print notify back-channel pipe handle*/
140         struct rpc_pipe_client *cli_pipe;
141         uint32_t active_connections;
142 };
143
144 static struct notify_back_channel *back_channels;
145
146 /* Map generic permissions to printer object specific permissions */
147
148 const struct standard_mapping printer_std_mapping = {
149         PRINTER_READ,
150         PRINTER_WRITE,
151         PRINTER_EXECUTE,
152         PRINTER_ALL_ACCESS
153 };
154
155 /* Map generic permissions to print server object specific permissions */
156
157 const struct standard_mapping printserver_std_mapping = {
158         SERVER_READ,
159         SERVER_WRITE,
160         SERVER_EXECUTE,
161         SERVER_ALL_ACCESS
162 };
163
164 /* API table for Xcv Monitor functions */
165
166 struct xcv_api_table {
167         const char *name;
168         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
169 };
170
171 static void prune_printername_cache(void);
172
173 /********************************************************************
174  * Canonicalize servername.
175  ********************************************************************/
176
177 static const char *canon_servername(const char *servername)
178 {
179         const char *pservername = servername;
180         while (*pservername == '\\') {
181                 pservername++;
182         }
183         return pservername;
184 }
185
186 /* translate between internal status numbers and NT status numbers */
187 static int nt_printj_status(int v)
188 {
189         switch (v) {
190         case LPQ_QUEUED:
191                 return 0;
192         case LPQ_PAUSED:
193                 return JOB_STATUS_PAUSED;
194         case LPQ_SPOOLING:
195                 return JOB_STATUS_SPOOLING;
196         case LPQ_PRINTING:
197                 return JOB_STATUS_PRINTING;
198         case LPQ_ERROR:
199                 return JOB_STATUS_ERROR;
200         case LPQ_DELETING:
201                 return JOB_STATUS_DELETING;
202         case LPQ_OFFLINE:
203                 return JOB_STATUS_OFFLINE;
204         case LPQ_PAPEROUT:
205                 return JOB_STATUS_PAPEROUT;
206         case LPQ_PRINTED:
207                 return JOB_STATUS_PRINTED;
208         case LPQ_DELETED:
209                 return JOB_STATUS_DELETED;
210         case LPQ_BLOCKED:
211                 return JOB_STATUS_BLOCKED_DEVQ;
212         case LPQ_USER_INTERVENTION:
213                 return JOB_STATUS_USER_INTERVENTION;
214         }
215         return 0;
216 }
217
218 static int nt_printq_status(int v)
219 {
220         switch (v) {
221         case LPQ_PAUSED:
222                 return PRINTER_STATUS_PAUSED;
223         case LPQ_QUEUED:
224         case LPQ_SPOOLING:
225         case LPQ_PRINTING:
226                 return 0;
227         }
228         return 0;
229 }
230
231 /***************************************************************************
232  Disconnect from the client
233 ****************************************************************************/
234
235 static void srv_spoolss_replycloseprinter(int snum,
236                                           struct printer_handle *prn_hnd)
237 {
238         WERROR result;
239         NTSTATUS status;
240
241         /*
242          * Tell the specific printing tdb we no longer want messages for this printer
243          * by deregistering our PID.
244          */
245
246         if (!print_notify_deregister_pid(snum)) {
247                 DEBUG(0, ("Failed to register our pid for printer %s\n",
248                           lp_const_servicename(snum)));
249         }
250
251         /* weird if the test succeeds !!! */
252         if (prn_hnd->notify.cli_chan == NULL ||
253             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
254             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
255             prn_hnd->notify.cli_chan->active_connections == 0) {
256                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
257                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
258                 TALLOC_FREE(prn_hnd->notify.cli_chan);
259                 return;
260         }
261
262         status = dcerpc_spoolss_ReplyClosePrinter(
263                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
264                                         talloc_tos(),
265                                         &prn_hnd->notify.cli_hnd,
266                                         &result);
267         if (!NT_STATUS_IS_OK(status)) {
268                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
269                           nt_errstr(status)));
270                 result = ntstatus_to_werror(status);
271         } else if (!W_ERROR_IS_OK(result)) {
272                 DEBUG(0, ("reply_close_printer failed [%s].\n",
273                           win_errstr(result)));
274         }
275
276         /* if it's the last connection, deconnect the IPC$ share */
277         if (prn_hnd->notify.cli_chan->active_connections == 1) {
278
279                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
280                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
281                 TALLOC_FREE(prn_hnd->notify.cli_chan);
282
283                 if (prn_hnd->notify.msg_ctx != NULL) {
284                         messaging_deregister(prn_hnd->notify.msg_ctx,
285                                              MSG_PRINTER_NOTIFY2, NULL);
286                 }
287         }
288
289         if (prn_hnd->notify.cli_chan) {
290                 prn_hnd->notify.cli_chan->active_connections--;
291         }
292 }
293
294 /****************************************************************************
295  Functions to free a printer entry datastruct.
296 ****************************************************************************/
297
298 static int printer_entry_destructor(struct printer_handle *Printer)
299 {
300         if (Printer->notify.cli_chan != NULL &&
301             Printer->notify.cli_chan->active_connections > 0) {
302                 int snum = -1;
303
304                 switch(Printer->printer_type) {
305                 case SPLHND_SERVER:
306                         srv_spoolss_replycloseprinter(snum, Printer);
307                         break;
308
309                 case SPLHND_PRINTER:
310                         snum = print_queue_snum(Printer->sharename);
311                         if (snum != -1) {
312                                 srv_spoolss_replycloseprinter(snum, Printer);
313                         }
314                         break;
315                 default:
316                         break;
317                 }
318         }
319
320         Printer->notify.flags=0;
321         Printer->notify.options=0;
322         Printer->notify.localmachine[0]='\0';
323         Printer->notify.printerlocal=0;
324         TALLOC_FREE(Printer->notify.option);
325         TALLOC_FREE(Printer->devmode);
326
327         /* Remove from the internal list. */
328         DLIST_REMOVE(printers_list, Printer);
329         return 0;
330 }
331
332 /****************************************************************************
333   find printer index by handle
334 ****************************************************************************/
335
336 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
337                                                         struct policy_handle *hnd)
338 {
339         struct printer_handle *find_printer = NULL;
340
341         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
342                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
343                 return NULL;
344         }
345
346         return find_printer;
347 }
348
349 /****************************************************************************
350  Close printer index by handle.
351 ****************************************************************************/
352
353 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
354 {
355         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
356
357         if (!Printer) {
358                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
359                         OUR_HANDLE(hnd)));
360                 return false;
361         }
362
363         close_policy_hnd(p, hnd);
364
365         return true;
366 }
367
368 /****************************************************************************
369  Delete a printer given a handle.
370 ****************************************************************************/
371
372 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
373                                   const char *sharename,
374                                   struct messaging_context *msg_ctx)
375 {
376         char *cmd = lp_deleteprinter_cmd();
377         char *command = NULL;
378         int ret;
379         bool is_print_op = false;
380
381         /* can't fail if we don't try */
382
383         if ( !*cmd )
384                 return WERR_OK;
385
386         command = talloc_asprintf(ctx,
387                         "%s \"%s\"",
388                         cmd, sharename);
389         if (!command) {
390                 return WERR_NOMEM;
391         }
392         if ( token )
393                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
394
395         DEBUG(10,("Running [%s]\n", command));
396
397         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
398
399         if ( is_print_op )
400                 become_root();
401
402         if ( (ret = smbrun(command, NULL)) == 0 ) {
403                 /* Tell everyone we updated smb.conf. */
404                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
405         }
406
407         if ( is_print_op )
408                 unbecome_root();
409
410         /********** END SePrintOperatorPrivlege BLOCK **********/
411
412         DEBUGADD(10,("returned [%d]\n", ret));
413
414         TALLOC_FREE(command);
415
416         if (ret != 0)
417                 return WERR_BADFID; /* What to return here? */
418
419         /* go ahead and re-read the services immediately */
420         become_root();
421         reload_services(msg_ctx, -1, false);
422         unbecome_root();
423
424         if ( lp_servicenumber( sharename ) >= 0 )
425                 return WERR_ACCESS_DENIED;
426
427         return WERR_OK;
428 }
429
430 /****************************************************************************
431  Delete a printer given a handle.
432 ****************************************************************************/
433
434 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
435 {
436         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
437         WERROR result;
438
439         if (!Printer) {
440                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
441                         OUR_HANDLE(hnd)));
442                 return WERR_BADFID;
443         }
444
445         /*
446          * It turns out that Windows allows delete printer on a handle
447          * opened by an admin user, then used on a pipe handle created
448          * by an anonymous user..... but they're working on security.... riiight !
449          * JRA.
450          */
451
452         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
453                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
454                 return WERR_ACCESS_DENIED;
455         }
456
457         /* this does not need a become root since the access check has been
458            done on the handle already */
459
460         result = winreg_delete_printer_key_internal(p->mem_ctx,
461                                            get_session_info_system(),
462                                            p->msg_ctx,
463                                            Printer->sharename,
464                                            "");
465         if (!W_ERROR_IS_OK(result)) {
466                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
467                 return WERR_BADFID;
468         }
469
470         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
471                                      Printer->sharename, p->msg_ctx);
472         if (!W_ERROR_IS_OK(result)) {
473                 return result;
474         }
475         prune_printername_cache();
476         return WERR_OK;
477 }
478
479 /****************************************************************************
480  Return the snum of a printer corresponding to an handle.
481 ****************************************************************************/
482
483 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
484                              int *number, struct share_params **params)
485 {
486         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
487
488         if (!Printer) {
489                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
490                         OUR_HANDLE(hnd)));
491                 return false;
492         }
493
494         switch (Printer->printer_type) {
495                 case SPLHND_PRINTER:
496                         DEBUG(4,("short name:%s\n", Printer->sharename));
497                         *number = print_queue_snum(Printer->sharename);
498                         return (*number != -1);
499                 case SPLHND_SERVER:
500                         return false;
501                 default:
502                         return false;
503         }
504 }
505
506 /****************************************************************************
507  Set printer handle type.
508  Check if it's \\server or \\server\printer
509 ****************************************************************************/
510
511 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
512 {
513         DEBUG(3,("Setting printer type=%s\n", handlename));
514
515         /* it's a print server */
516         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
517                 DEBUGADD(4,("Printer is a print server\n"));
518                 Printer->printer_type = SPLHND_SERVER;
519         }
520         /* it's a printer (set_printer_hnd_name() will handle port monitors */
521         else {
522                 DEBUGADD(4,("Printer is a printer\n"));
523                 Printer->printer_type = SPLHND_PRINTER;
524         }
525
526         return true;
527 }
528
529 static void prune_printername_cache_fn(const char *key, const char *value,
530                                        time_t timeout, void *private_data)
531 {
532         gencache_del(key);
533 }
534
535 static void prune_printername_cache(void)
536 {
537         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
538 }
539
540 /****************************************************************************
541  Set printer handle name..  Accept names like \\server, \\server\printer,
542  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
543  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
544  XcvDataPort() interface.
545 ****************************************************************************/
546
547 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
548                                    const struct auth_session_info *session_info,
549                                    struct messaging_context *msg_ctx,
550                                    struct printer_handle *Printer,
551                                    const char *handlename)
552 {
553         int snum;
554         int n_services=lp_numservices();
555         char *aprinter;
556         const char *printername;
557         const char *servername = NULL;
558         fstring sname;
559         bool found = false;
560         struct spoolss_PrinterInfo2 *info2 = NULL;
561         WERROR result;
562         char *p;
563
564         /*
565          * Hopefully nobody names his printers like this. Maybe \ or ,
566          * are illegal in printer names even?
567          */
568         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
569         char *cache_key;
570         char *tmp;
571
572         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
573                 (unsigned long)strlen(handlename)));
574
575         aprinter = discard_const_p(char, handlename);
576         if ( *handlename == '\\' ) {
577                 servername = canon_servername(handlename);
578                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
579                         *aprinter = '\0';
580                         aprinter++;
581                 }
582                 if (!is_myname_or_ipaddr(servername)) {
583                         return WERR_INVALID_PRINTER_NAME;
584                 }
585                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
586                 if (Printer->servername == NULL) {
587                         return WERR_NOMEM;
588                 }
589         }
590
591         if (Printer->printer_type == SPLHND_SERVER) {
592                 return WERR_OK;
593         }
594
595         if (Printer->printer_type != SPLHND_PRINTER) {
596                 return WERR_INVALID_HANDLE;
597         }
598
599         DEBUGADD(5, ("searching for [%s]\n", aprinter));
600
601         p = strchr(aprinter, ',');
602         if (p != NULL) {
603                 char *p2 = p;
604                 p++;
605                 if (*p == ' ') {
606                         p++;
607                 }
608                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
609                         *p2 = '\0';
610                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
611                         *p2 = '\0';
612                 }
613         }
614
615         if (p) {
616                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
617         }
618
619         /* check for the Port Monitor Interface */
620         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
621                 Printer->printer_type = SPLHND_PORTMON_TCP;
622                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
623                 found = true;
624         }
625         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
626                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
627                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
628                 found = true;
629         }
630
631         /*
632          * With hundreds of printers, the "for" loop iterating all
633          * shares can be quite expensive, as it is done on every
634          * OpenPrinter. The loop maps "aprinter" to "sname", the
635          * result of which we cache in gencache.
636          */
637
638         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
639                                     aprinter);
640         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
641
642                 found = (strcmp(tmp, printer_not_found) != 0);
643                 if (!found) {
644                         DEBUG(4, ("Printer %s not found\n", aprinter));
645                         SAFE_FREE(tmp);
646                         return WERR_INVALID_PRINTER_NAME;
647                 }
648                 fstrcpy(sname, tmp);
649                 SAFE_FREE(tmp);
650         }
651
652         /* Search all sharenames first as this is easier than pulling
653            the printer_info_2 off of disk. Don't use find_service() since
654            that calls out to map_username() */
655
656         /* do another loop to look for printernames */
657         for (snum = 0; !found && snum < n_services; snum++) {
658                 const char *printer = lp_const_servicename(snum);
659
660                 /* no point going on if this is not a printer */
661                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
662                         continue;
663                 }
664
665                 /* ignore [printers] share */
666                 if (strequal(printer, "printers")) {
667                         continue;
668                 }
669
670                 fstrcpy(sname, printer);
671                 if (strequal(aprinter, printer)) {
672                         found = true;
673                         break;
674                 }
675
676                 /* no point looking up the printer object if
677                    we aren't allowing printername != sharename */
678                 if (lp_force_printername(snum)) {
679                         continue;
680                 }
681
682                 result = winreg_get_printer_internal(mem_ctx,
683                                             session_info,
684                                             msg_ctx,
685                                             sname,
686                                             &info2);
687                 if ( !W_ERROR_IS_OK(result) ) {
688                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
689                                  sname, win_errstr(result)));
690                         continue;
691                 }
692
693                 printername = strrchr(info2->printername, '\\');
694                 if (printername == NULL) {
695                         printername = info2->printername;
696                 } else {
697                         printername++;
698                 }
699
700                 if (strequal(printername, aprinter)) {
701                         found = true;
702                         break;
703                 }
704
705                 DEBUGADD(10, ("printername: %s\n", printername));
706
707                 TALLOC_FREE(info2);
708         }
709
710         if ( !found ) {
711                 if (cache_key != NULL) {
712                         gencache_set(cache_key, printer_not_found,
713                                      time(NULL)+300);
714                         TALLOC_FREE(cache_key);
715                 }
716                 DEBUGADD(4,("Printer not found\n"));
717                 return WERR_INVALID_PRINTER_NAME;
718         }
719
720         if (cache_key != NULL) {
721                 gencache_set(cache_key, sname, time(NULL)+300);
722                 TALLOC_FREE(cache_key);
723         }
724
725         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
726
727         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
728
729         return WERR_OK;
730 }
731
732 /****************************************************************************
733  Find first available printer slot. creates a printer handle for you.
734  ****************************************************************************/
735
736 static WERROR open_printer_hnd(struct pipes_struct *p,
737                                struct policy_handle *hnd,
738                                const char *name,
739                                uint32_t access_granted)
740 {
741         struct printer_handle *new_printer;
742         WERROR result;
743
744         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
745
746         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
747         if (new_printer == NULL) {
748                 return WERR_NOMEM;
749         }
750         talloc_set_destructor(new_printer, printer_entry_destructor);
751
752         /* This also steals the printer_handle on the policy_handle */
753         if (!create_policy_hnd(p, hnd, new_printer)) {
754                 TALLOC_FREE(new_printer);
755                 return WERR_INVALID_HANDLE;
756         }
757
758         /* Add to the internal list. */
759         DLIST_ADD(printers_list, new_printer);
760
761         new_printer->notify.option=NULL;
762
763         if (!set_printer_hnd_printertype(new_printer, name)) {
764                 close_printer_handle(p, hnd);
765                 return WERR_INVALID_HANDLE;
766         }
767
768         result = set_printer_hnd_name(p->mem_ctx,
769                                       get_session_info_system(),
770                                       p->msg_ctx,
771                                       new_printer, name);
772         if (!W_ERROR_IS_OK(result)) {
773                 close_printer_handle(p, hnd);
774                 return result;
775         }
776
777         new_printer->access_granted = access_granted;
778
779         DEBUG(5, ("%d printer handles active\n",
780                   (int)num_pipe_handles(p)));
781
782         return WERR_OK;
783 }
784
785 /***************************************************************************
786  check to see if the client motify handle is monitoring the notification
787  given by (notify_type, notify_field).
788  **************************************************************************/
789
790 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
791                                       uint16_t notify_field)
792 {
793         return true;
794 }
795
796 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
797                                 uint16_t notify_field)
798 {
799         struct spoolss_NotifyOption *option = p->notify.option;
800         uint32_t i, j;
801
802         /*
803          * Flags should always be zero when the change notify
804          * is registered by the client's spooler.  A user Win32 app
805          * might use the flags though instead of the NOTIFY_OPTION_INFO
806          * --jerry
807          */
808
809         if (!option) {
810                 return false;
811         }
812
813         if (p->notify.flags)
814                 return is_monitoring_event_flags(
815                         p->notify.flags, notify_type, notify_field);
816
817         for (i = 0; i < option->count; i++) {
818
819                 /* Check match for notify_type */
820
821                 if (option->types[i].type != notify_type)
822                         continue;
823
824                 /* Check match for field */
825
826                 for (j = 0; j < option->types[i].count; j++) {
827                         if (option->types[i].fields[j].field == notify_field) {
828                                 return true;
829                         }
830                 }
831         }
832
833         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
834                    p->servername, p->sharename, notify_type, notify_field));
835
836         return false;
837 }
838
839 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
840         _data->data.integer[0] = _integer; \
841         _data->data.integer[1] = 0;
842
843
844 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
845         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
846         if (!_data->data.string.string) {\
847                 _data->data.string.size = 0; \
848         } \
849         _data->data.string.size = strlen_m_term(_p) * 2;
850
851 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
852         _data->data.devmode.devmode = _devmode;
853
854 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
855         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
856         if (!_data->data.sd.sd) { \
857                 _data->data.sd.sd_size = 0; \
858         } \
859         _data->data.sd.sd_size = \
860                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
861
862 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
863                                    struct tm *t,
864                                    const char **pp,
865                                    uint32_t *plen)
866 {
867         struct spoolss_Time st;
868         uint32_t len = 16;
869         char *p;
870
871         if (!init_systemtime(&st, t)) {
872                 return;
873         }
874
875         p = talloc_array(mem_ctx, char, len);
876         if (!p) {
877                 return;
878         }
879
880         /*
881          * Systemtime must be linearized as a set of UINT16's.
882          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
883          */
884
885         SSVAL(p, 0, st.year);
886         SSVAL(p, 2, st.month);
887         SSVAL(p, 4, st.day_of_week);
888         SSVAL(p, 6, st.day);
889         SSVAL(p, 8, st.hour);
890         SSVAL(p, 10, st.minute);
891         SSVAL(p, 12, st.second);
892         SSVAL(p, 14, st.millisecond);
893
894         *pp = p;
895         *plen = len;
896 }
897
898 /* Convert a notification message to a struct spoolss_Notify */
899
900 static void notify_one_value(struct spoolss_notify_msg *msg,
901                              struct spoolss_Notify *data,
902                              TALLOC_CTX *mem_ctx)
903 {
904         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
905 }
906
907 static void notify_string(struct spoolss_notify_msg *msg,
908                           struct spoolss_Notify *data,
909                           TALLOC_CTX *mem_ctx)
910 {
911         /* The length of the message includes the trailing \0 */
912
913         data->data.string.size = msg->len * 2;
914         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
915         if (!data->data.string.string) {
916                 data->data.string.size = 0;
917                 return;
918         }
919 }
920
921 static void notify_system_time(struct spoolss_notify_msg *msg,
922                                struct spoolss_Notify *data,
923                                TALLOC_CTX *mem_ctx)
924 {
925         data->data.string.string = NULL;
926         data->data.string.size = 0;
927
928         if (msg->len != sizeof(time_t)) {
929                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
930                           msg->len));
931                 return;
932         }
933
934         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
935                                &data->data.string.string,
936                                &data->data.string.size);
937 }
938
939 struct notify2_message_table {
940         const char *name;
941         void (*fn)(struct spoolss_notify_msg *msg,
942                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
943 };
944
945 static struct notify2_message_table printer_notify_table[] = {
946         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
947         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
948         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
949         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
950         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
951         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
952         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
953         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
954         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
955         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
956         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
957         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
958         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
959         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
960         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
961         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
962         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
963         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
964         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
965 };
966
967 static struct notify2_message_table job_notify_table[] = {
968         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
969         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
970         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
971         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
972         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
973         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
974         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
975         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
976         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
977         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
978         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
979         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
980         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
981         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
982         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
983         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
984         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
985         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
986         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
987         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
988         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
989         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
990         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
991         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
992 };
993
994
995 /***********************************************************************
996  Allocate talloc context for container object
997  **********************************************************************/
998
999 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1000 {
1001         if ( !ctr )
1002                 return;
1003
1004         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1005
1006         return;
1007 }
1008
1009 /***********************************************************************
1010  release all allocated memory and zero out structure
1011  **********************************************************************/
1012
1013 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1014 {
1015         if ( !ctr )
1016                 return;
1017
1018         if ( ctr->ctx )
1019                 talloc_destroy(ctr->ctx);
1020
1021         ZERO_STRUCTP(ctr);
1022
1023         return;
1024 }
1025
1026 /***********************************************************************
1027  **********************************************************************/
1028
1029 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1030 {
1031         if ( !ctr )
1032                 return NULL;
1033
1034         return ctr->ctx;
1035 }
1036
1037 /***********************************************************************
1038  **********************************************************************/
1039
1040 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1041 {
1042         if ( !ctr || !ctr->msg_groups )
1043                 return NULL;
1044
1045         if ( idx >= ctr->num_groups )
1046                 return NULL;
1047
1048         return &ctr->msg_groups[idx];
1049
1050 }
1051
1052 /***********************************************************************
1053  How many groups of change messages do we have ?
1054  **********************************************************************/
1055
1056 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1057 {
1058         if ( !ctr )
1059                 return 0;
1060
1061         return ctr->num_groups;
1062 }
1063
1064 /***********************************************************************
1065  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1066  **********************************************************************/
1067
1068 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1069 {
1070         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1071         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1072         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1073         int                             i, new_slot;
1074
1075         if ( !ctr || !msg )
1076                 return 0;
1077
1078         /* loop over all groups looking for a matching printer name */
1079
1080         for ( i=0; i<ctr->num_groups; i++ ) {
1081                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1082                         break;
1083         }
1084
1085         /* add a new group? */
1086
1087         if ( i == ctr->num_groups ) {
1088                 ctr->num_groups++;
1089
1090                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1091                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1092                         return 0;
1093                 }
1094                 ctr->msg_groups = groups;
1095
1096                 /* clear the new entry and set the printer name */
1097
1098                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1099                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1100         }
1101
1102         /* add the change messages; 'i' is the correct index now regardless */
1103
1104         msg_grp = &ctr->msg_groups[i];
1105
1106         msg_grp->num_msgs++;
1107
1108         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1109                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1110                 return 0;
1111         }
1112         msg_grp->msgs = msg_list;
1113
1114         new_slot = msg_grp->num_msgs-1;
1115         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1116
1117         /* need to allocate own copy of data */
1118
1119         if ( msg->len != 0 )
1120                 msg_grp->msgs[new_slot].notify.data = (char *)
1121                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1122
1123         return ctr->num_groups;
1124 }
1125
1126 static void construct_info_data(struct spoolss_Notify *info_data,
1127                                 enum spoolss_NotifyType type,
1128                                 uint16_t field, int id);
1129
1130 /***********************************************************************
1131  Send a change notication message on all handles which have a call
1132  back registered
1133  **********************************************************************/
1134
1135 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1136                                   struct printer_handle *prn_hnd,
1137                                   SPOOLSS_NOTIFY_MSG *messages,
1138                                   uint32_t num_msgs,
1139                                   struct spoolss_Notify **_notifies,
1140                                   int *_count)
1141 {
1142         struct spoolss_Notify *notifies;
1143         SPOOLSS_NOTIFY_MSG *msg;
1144         int count = 0;
1145         uint32_t id;
1146         int i;
1147
1148         notifies = talloc_zero_array(mem_ctx,
1149                                      struct spoolss_Notify, num_msgs);
1150         if (!notifies) {
1151                 return ENOMEM;
1152         }
1153
1154         for (i = 0; i < num_msgs; i++) {
1155
1156                 msg = &messages[i];
1157
1158                 /* Are we monitoring this event? */
1159
1160                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1161                         continue;
1162                 }
1163
1164                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1165                            "for printer [%s]\n",
1166                            msg->type, msg->field, prn_hnd->sharename));
1167
1168                 /*
1169                  * if the is a printer notification handle and not a job
1170                  * notification type, then set the id to 0.
1171                  * Otherwise just use what was specified in the message.
1172                  *
1173                  * When registering change notification on a print server
1174                  * handle we always need to send back the id (snum) matching
1175                  * the printer for which the change took place.
1176                  * For change notify registered on a printer handle,
1177                  * this does not matter and the id should be 0.
1178                  *
1179                  * --jerry
1180                  */
1181
1182                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1183                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1184                         id = 0;
1185                 } else {
1186                         id = msg->id;
1187                 }
1188
1189                 /* Convert unix jobid to smb jobid */
1190
1191                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1192                         id = sysjob_to_jobid(msg->id);
1193
1194                         if (id == -1) {
1195                                 DEBUG(3, ("no such unix jobid %d\n",
1196                                           msg->id));
1197                                 continue;
1198                         }
1199                 }
1200
1201                 construct_info_data(&notifies[count],
1202                                     msg->type, msg->field, id);
1203
1204                 switch(msg->type) {
1205                 case PRINTER_NOTIFY_TYPE:
1206                         if (printer_notify_table[msg->field].fn) {
1207                                 printer_notify_table[msg->field].fn(msg,
1208                                                 &notifies[count], mem_ctx);
1209                         }
1210                         break;
1211
1212                 case JOB_NOTIFY_TYPE:
1213                         if (job_notify_table[msg->field].fn) {
1214                                 job_notify_table[msg->field].fn(msg,
1215                                                 &notifies[count], mem_ctx);
1216                         }
1217                         break;
1218
1219                 default:
1220                         DEBUG(5, ("Unknown notification type %d\n",
1221                                   msg->type));
1222                         continue;
1223                 }
1224
1225                 count++;
1226         }
1227
1228         *_notifies = notifies;
1229         *_count = count;
1230
1231         return 0;
1232 }
1233
1234 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1235                                 struct printer_handle *prn_hnd,
1236                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1237 {
1238         struct spoolss_Notify *notifies;
1239         int count = 0;
1240         union spoolss_ReplyPrinterInfo info;
1241         struct spoolss_NotifyInfo info0;
1242         uint32_t reply_result;
1243         NTSTATUS status;
1244         WERROR werr;
1245         int ret;
1246
1247         /* Is there notification on this handle? */
1248         if (prn_hnd->notify.cli_chan == NULL ||
1249             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1250             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1251             prn_hnd->notify.cli_chan->active_connections == 0) {
1252                 return 0;
1253         }
1254
1255         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1256                    prn_hnd->servername, prn_hnd->sharename));
1257
1258         /* For this printer? Print servers always receive notifications. */
1259         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1260             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1261                 return 0;
1262         }
1263
1264         DEBUG(10,("Our printer\n"));
1265
1266         /* build the array of change notifications */
1267         ret = build_notify2_messages(mem_ctx, prn_hnd,
1268                                      msg_group->msgs,
1269                                      msg_group->num_msgs,
1270                                      &notifies, &count);
1271         if (ret) {
1272                 return ret;
1273         }
1274
1275         info0.version   = 0x2;
1276         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1277         info0.count     = count;
1278         info0.notifies  = notifies;
1279
1280         info.info0 = &info0;
1281
1282         status = dcerpc_spoolss_RouterReplyPrinterEx(
1283                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1284                                 mem_ctx,
1285                                 &prn_hnd->notify.cli_hnd,
1286                                 prn_hnd->notify.change, /* color */
1287                                 prn_hnd->notify.flags,
1288                                 &reply_result,
1289                                 0, /* reply_type, must be 0 */
1290                                 info, &werr);
1291         if (!NT_STATUS_IS_OK(status)) {
1292                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1293                           "failed: %s\n",
1294                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1295                           nt_errstr(status)));
1296                 werr = ntstatus_to_werror(status);
1297         } else if (!W_ERROR_IS_OK(werr)) {
1298                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1299                           "failed: %s\n",
1300                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1301                           win_errstr(werr)));
1302         }
1303         switch (reply_result) {
1304         case 0:
1305                 break;
1306         case PRINTER_NOTIFY_INFO_DISCARDED:
1307         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1308         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1309                 break;
1310         default:
1311                 break;
1312         }
1313
1314         return 0;
1315 }
1316
1317 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1318 {
1319         struct printer_handle    *p;
1320         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1321         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1322         int ret;
1323
1324         if ( !msg_group ) {
1325                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1326                 return;
1327         }
1328
1329         if (!msg_group->msgs) {
1330                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1331                 return;
1332         }
1333
1334         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1335
1336         /* loop over all printers */
1337
1338         for (p = printers_list; p; p = p->next) {
1339                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1340                 if (ret) {
1341                         goto done;
1342                 }
1343         }
1344
1345 done:
1346         DEBUG(8,("send_notify2_changes: Exit...\n"));
1347         return;
1348 }
1349
1350 /***********************************************************************
1351  **********************************************************************/
1352
1353 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1354 {
1355
1356         uint32_t tv_sec, tv_usec;
1357         size_t offset = 0;
1358
1359         /* Unpack message */
1360
1361         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1362                              msg->printer);
1363
1364         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1365                                 &tv_sec, &tv_usec,
1366                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1367
1368         if (msg->len == 0)
1369                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1370                            &msg->notify.value[0], &msg->notify.value[1]);
1371         else
1372                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1373                            &msg->len, &msg->notify.data);
1374
1375         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1376                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1377
1378         tv->tv_sec = tv_sec;
1379         tv->tv_usec = tv_usec;
1380
1381         if (msg->len == 0)
1382                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1383                           msg->notify.value[1]));
1384         else
1385                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1386
1387         return true;
1388 }
1389
1390 /********************************************************************
1391  Receive a notify2 message list
1392  ********************************************************************/
1393
1394 static void receive_notify2_message_list(struct messaging_context *msg,
1395                                          void *private_data,
1396                                          uint32_t msg_type,
1397                                          struct server_id server_id,
1398                                          DATA_BLOB *data)
1399 {
1400         size_t                  msg_count, i;
1401         char                    *buf = (char *)data->data;
1402         char                    *msg_ptr;
1403         size_t                  msg_len;
1404         SPOOLSS_NOTIFY_MSG      notify;
1405         SPOOLSS_NOTIFY_MSG_CTR  messages;
1406         int                     num_groups;
1407
1408         if (data->length < 4) {
1409                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1410                 return;
1411         }
1412
1413         msg_count = IVAL(buf, 0);
1414         msg_ptr = buf + 4;
1415
1416         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1417
1418         if (msg_count == 0) {
1419                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1420                 return;
1421         }
1422
1423         /* initialize the container */
1424
1425         ZERO_STRUCT( messages );
1426         notify_msg_ctr_init( &messages );
1427
1428         /*
1429          * build message groups for each printer identified
1430          * in a change_notify msg.  Remember that a PCN message
1431          * includes the handle returned for the srv_spoolss_replyopenprinter()
1432          * call.  Therefore messages are grouped according to printer handle.
1433          */
1434
1435         for ( i=0; i<msg_count; i++ ) {
1436                 struct timeval msg_tv;
1437
1438                 if (msg_ptr + 4 - buf > data->length) {
1439                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1440                         return;
1441                 }
1442
1443                 msg_len = IVAL(msg_ptr,0);
1444                 msg_ptr += 4;
1445
1446                 if (msg_ptr + msg_len - buf > data->length) {
1447                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1448                         return;
1449                 }
1450
1451                 /* unpack messages */
1452
1453                 ZERO_STRUCT( notify );
1454                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1455                 msg_ptr += msg_len;
1456
1457                 /* add to correct list in container */
1458
1459                 notify_msg_ctr_addmsg( &messages, &notify );
1460
1461                 /* free memory that might have been allocated by notify2_unpack_msg() */
1462
1463                 if ( notify.len != 0 )
1464                         SAFE_FREE( notify.notify.data );
1465         }
1466
1467         /* process each group of messages */
1468
1469         num_groups = notify_msg_ctr_numgroups( &messages );
1470         for ( i=0; i<num_groups; i++ )
1471                 send_notify2_changes( &messages, i );
1472
1473
1474         /* cleanup */
1475
1476         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1477                 (uint32_t)msg_count ));
1478
1479         notify_msg_ctr_destroy( &messages );
1480
1481         return;
1482 }
1483
1484 /********************************************************************
1485  Send a message to ourself about new driver being installed
1486  so we can upgrade the information for each printer bound to this
1487  driver
1488  ********************************************************************/
1489
1490 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1491                                             struct messaging_context *msg_ctx)
1492 {
1493         int len = strlen(drivername);
1494
1495         if (!len)
1496                 return false;
1497
1498         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1499                 drivername));
1500
1501         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1502                            MSG_PRINTER_DRVUPGRADE,
1503                            (const uint8_t *)drivername, len+1);
1504
1505         return true;
1506 }
1507
1508 void srv_spoolss_cleanup(void)
1509 {
1510         struct printer_session_counter *session_counter;
1511
1512         for (session_counter = counter_list;
1513              session_counter != NULL;
1514              session_counter = counter_list) {
1515                 DLIST_REMOVE(counter_list, session_counter);
1516                 TALLOC_FREE(session_counter);
1517         }
1518 }
1519
1520 /**********************************************************************
1521  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1522  over all printers, upgrading ones as necessary
1523  **********************************************************************/
1524
1525 void do_drv_upgrade_printer(struct messaging_context *msg,
1526                             void *private_data,
1527                             uint32_t msg_type,
1528                             struct server_id server_id,
1529                             DATA_BLOB *data)
1530 {
1531         TALLOC_CTX *tmp_ctx;
1532         const struct auth_session_info *session_info = get_session_info_system();
1533         struct spoolss_PrinterInfo2 *pinfo2;
1534         WERROR result;
1535         const char *drivername;
1536         int snum;
1537         int n_services = lp_numservices();
1538         struct dcerpc_binding_handle *b = NULL;
1539
1540         tmp_ctx = talloc_new(NULL);
1541         if (!tmp_ctx) return;
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                 if (b == NULL) {
1565                         result = winreg_printer_binding_handle(tmp_ctx,
1566                                                                session_info,
1567                                                                msg,
1568                                                                &b);
1569                         if (!W_ERROR_IS_OK(result)) {
1570                                 break;
1571                         }
1572                 }
1573
1574                 result = winreg_get_printer(tmp_ctx, b,
1575                                             lp_const_servicename(snum),
1576                                             &pinfo2);
1577
1578                 if (!W_ERROR_IS_OK(result)) {
1579                         continue;
1580                 }
1581
1582                 if (!pinfo2->drivername) {
1583                         continue;
1584                 }
1585
1586                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1587                         continue;
1588                 }
1589
1590                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1591
1592                 /* all we care about currently is the change_id */
1593                 result = winreg_printer_update_changeid(tmp_ctx, b,
1594                                                         pinfo2->printername);
1595
1596                 if (!W_ERROR_IS_OK(result)) {
1597                         DEBUG(3, ("do_drv_upgrade_printer: "
1598                                   "Failed to update changeid [%s]\n",
1599                                   win_errstr(result)));
1600                 }
1601         }
1602
1603         /* all done */
1604 done:
1605         talloc_free(tmp_ctx);
1606 }
1607
1608 /********************************************************************
1609  Update the cache for all printq's with a registered client
1610  connection
1611  ********************************************************************/
1612
1613 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1614 {
1615         struct printer_handle *printer = printers_list;
1616         int snum;
1617
1618         /* loop through all printers and update the cache where
1619            a client is connected */
1620         while (printer) {
1621                 if ((printer->printer_type == SPLHND_PRINTER) &&
1622                     ((printer->notify.cli_chan != NULL) &&
1623                      (printer->notify.cli_chan->active_connections > 0))) {
1624                         snum = print_queue_snum(printer->sharename);
1625                         print_queue_status(msg_ctx, snum, NULL, NULL);
1626                 }
1627
1628                 printer = printer->next;
1629         }
1630
1631         return;
1632 }
1633
1634 /****************************************************************
1635  _spoolss_OpenPrinter
1636 ****************************************************************/
1637
1638 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1639                             struct spoolss_OpenPrinter *r)
1640 {
1641         struct spoolss_OpenPrinterEx e;
1642         WERROR werr;
1643
1644         ZERO_STRUCT(e.in.userlevel);
1645
1646         e.in.printername        = r->in.printername;
1647         e.in.datatype           = r->in.datatype;
1648         e.in.devmode_ctr        = r->in.devmode_ctr;
1649         e.in.access_mask        = r->in.access_mask;
1650         e.in.level              = 0;
1651
1652         e.out.handle            = r->out.handle;
1653
1654         werr = _spoolss_OpenPrinterEx(p, &e);
1655
1656         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1657                 /* OpenPrinterEx returns this for a bad
1658                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1659                  * instead.
1660                  */
1661                 werr = WERR_INVALID_PRINTER_NAME;
1662         }
1663
1664         return werr;
1665 }
1666
1667 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1668                               struct spoolss_DeviceMode *orig,
1669                               struct spoolss_DeviceMode **dest)
1670 {
1671         struct spoolss_DeviceMode *dm;
1672
1673         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1674         if (!dm) {
1675                 return WERR_NOMEM;
1676         }
1677
1678         /* copy all values, then duplicate strings and structs */
1679         *dm = *orig;
1680
1681         dm->devicename = talloc_strdup(dm, orig->devicename);
1682         if (!dm->devicename) {
1683                 return WERR_NOMEM;
1684         }
1685         dm->formname = talloc_strdup(dm, orig->formname);
1686         if (!dm->formname) {
1687                 return WERR_NOMEM;
1688         }
1689         if (orig->driverextra_data.data) {
1690                 dm->driverextra_data.data =
1691                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1692                                         orig->driverextra_data.length);
1693                 if (!dm->driverextra_data.data) {
1694                         return WERR_NOMEM;
1695                 }
1696         }
1697
1698         *dest = dm;
1699         return WERR_OK;
1700 }
1701
1702 /****************************************************************
1703  _spoolss_OpenPrinterEx
1704 ****************************************************************/
1705
1706 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1707                               struct spoolss_OpenPrinterEx *r)
1708 {
1709         int snum;
1710         char *raddr;
1711         char *rhost;
1712         struct printer_handle *Printer=NULL;
1713         WERROR result;
1714         int rc;
1715
1716         if (!r->in.printername) {
1717                 return WERR_INVALID_PARAM;
1718         }
1719
1720         if (r->in.level > 3) {
1721                 return WERR_INVALID_PARAM;
1722         }
1723         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1724             (r->in.level == 2 && !r->in.userlevel.level2) ||
1725             (r->in.level == 3 && !r->in.userlevel.level3)) {
1726                 return WERR_INVALID_PARAM;
1727         }
1728
1729         /* some sanity check because you can open a printer or a print server */
1730         /* aka: \\server\printer or \\server */
1731
1732         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1733
1734         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1735         if (!W_ERROR_IS_OK(result)) {
1736                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1737                         "for printer %s\n", r->in.printername));
1738                 ZERO_STRUCTP(r->out.handle);
1739                 return result;
1740         }
1741
1742         Printer = find_printer_index_by_hnd(p, r->out.handle);
1743         if ( !Printer ) {
1744                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1745                         "handle we created for printer %s\n", r->in.printername));
1746                 close_printer_handle(p, r->out.handle);
1747                 ZERO_STRUCTP(r->out.handle);
1748                 return WERR_INVALID_PARAM;
1749         }
1750
1751         /*
1752          * First case: the user is opening the print server:
1753          *
1754          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1755          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1756          *
1757          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1758          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1759          * or if the user is listed in the smb.conf printer admin parameter.
1760          *
1761          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1762          * client view printer folder, but does not show the MSAPW.
1763          *
1764          * Note: this test needs code to check access rights here too. Jeremy
1765          * could you look at this?
1766          *
1767          * Second case: the user is opening a printer:
1768          * NT doesn't let us connect to a printer if the connecting user
1769          * doesn't have print permission.
1770          *
1771          * Third case: user is opening a Port Monitor
1772          * access checks same as opening a handle to the print server.
1773          */
1774
1775         switch (Printer->printer_type )
1776         {
1777         case SPLHND_SERVER:
1778         case SPLHND_PORTMON_TCP:
1779         case SPLHND_PORTMON_LOCAL:
1780                 /* Printserver handles use global struct... */
1781
1782                 snum = -1;
1783
1784                 /* Map standard access rights to object specific access rights */
1785
1786                 se_map_standard(&r->in.access_mask,
1787                                 &printserver_std_mapping);
1788
1789                 /* Deny any object specific bits that don't apply to print
1790                    servers (i.e printer and job specific bits) */
1791
1792                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1793
1794                 if (r->in.access_mask &
1795                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1796                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1797                         close_printer_handle(p, r->out.handle);
1798                         ZERO_STRUCTP(r->out.handle);
1799                         return WERR_ACCESS_DENIED;
1800                 }
1801
1802                 /* Allow admin access */
1803
1804                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1805                 {
1806                         if (!lp_ms_add_printer_wizard()) {
1807                                 close_printer_handle(p, r->out.handle);
1808                                 ZERO_STRUCTP(r->out.handle);
1809                                 return WERR_ACCESS_DENIED;
1810                         }
1811
1812                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1813                            and not a printer admin, then fail */
1814
1815                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1816                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1817                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1818                             !token_contains_name_in_list(
1819                                     uidtoname(p->session_info->unix_token->uid),
1820                                     p->session_info->info->domain_name,
1821                                     NULL,
1822                                     p->session_info->security_token,
1823                                     lp_printer_admin(snum))) {
1824                                 close_printer_handle(p, r->out.handle);
1825                                 ZERO_STRUCTP(r->out.handle);
1826                                 DEBUG(3,("access DENIED as user is not root, "
1827                                         "has no printoperator privilege, "
1828                                         "not a member of the printoperator builtin group and "
1829                                         "is not in printer admin list"));
1830                                 return WERR_ACCESS_DENIED;
1831                         }
1832
1833                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1834                 }
1835                 else
1836                 {
1837                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1838                 }
1839
1840                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1841                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1842
1843                 /* We fall through to return WERR_OK */
1844                 break;
1845
1846         case SPLHND_PRINTER:
1847                 /* NT doesn't let us connect to a printer if the connecting user
1848                    doesn't have print permission.  */
1849
1850                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1851                         close_printer_handle(p, r->out.handle);
1852                         ZERO_STRUCTP(r->out.handle);
1853                         return WERR_BADFID;
1854                 }
1855
1856                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1857                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1858                 }
1859
1860                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1861
1862                 /* map an empty access mask to the minimum access mask */
1863                 if (r->in.access_mask == 0x0)
1864                         r->in.access_mask = PRINTER_ACCESS_USE;
1865
1866                 /*
1867                  * If we are not serving the printer driver for this printer,
1868                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1869                  * will keep NT clients happy  --jerry
1870                  */
1871
1872                 if (lp_use_client_driver(snum)
1873                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1874                 {
1875                         r->in.access_mask = PRINTER_ACCESS_USE;
1876                 }
1877
1878                 /* check smb.conf parameters and the the sec_desc */
1879                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1880                                                          p->mem_ctx);
1881                 if (raddr == NULL) {
1882                         return WERR_NOMEM;
1883                 }
1884
1885                 rc = get_remote_hostname(p->remote_address,
1886                                          &rhost,
1887                                          p->mem_ctx);
1888                 if (rc < 0) {
1889                         return WERR_NOMEM;
1890                 }
1891                 if (strequal(rhost, "UNKNOWN")) {
1892                         rhost = raddr;
1893                 }
1894
1895                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1896                                   rhost, raddr)) {
1897                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1898                         ZERO_STRUCTP(r->out.handle);
1899                         return WERR_ACCESS_DENIED;
1900                 }
1901
1902                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1903                                    p->session_info->security_token, snum) ||
1904                     !print_access_check(p->session_info,
1905                                         p->msg_ctx,
1906                                         snum,
1907                                         r->in.access_mask)) {
1908                         DEBUG(3, ("access DENIED for printer open\n"));
1909                         close_printer_handle(p, r->out.handle);
1910                         ZERO_STRUCTP(r->out.handle);
1911                         return WERR_ACCESS_DENIED;
1912                 }
1913
1914                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1915                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1916                         close_printer_handle(p, r->out.handle);
1917                         ZERO_STRUCTP(r->out.handle);
1918                         return WERR_ACCESS_DENIED;
1919                 }
1920
1921                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1922                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1923                 else
1924                         r->in.access_mask = PRINTER_ACCESS_USE;
1925
1926                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1927                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1928
1929                 winreg_create_printer_internal(p->mem_ctx,
1930                                       get_session_info_system(),
1931                                       p->msg_ctx,
1932                                       lp_const_servicename(snum));
1933
1934                 break;
1935
1936         default:
1937                 /* sanity check to prevent programmer error */
1938                 ZERO_STRUCTP(r->out.handle);
1939                 return WERR_BADFID;
1940         }
1941
1942         Printer->access_granted = r->in.access_mask;
1943
1944         /*
1945          * If the client sent a devmode in the OpenPrinter() call, then
1946          * save it here in case we get a job submission on this handle
1947          */
1948
1949          if ((Printer->printer_type != SPLHND_SERVER) &&
1950              r->in.devmode_ctr.devmode) {
1951                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1952                                 &Printer->devmode);
1953          }
1954
1955 #if 0   /* JERRY -- I'm doubtful this is really effective */
1956         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1957            optimization in Windows 2000 clients  --jerry */
1958
1959         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1960                 && (RA_WIN2K == get_remote_arch()) )
1961         {
1962                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1963                 sys_usleep( 500000 );
1964         }
1965 #endif
1966
1967         return WERR_OK;
1968 }
1969
1970 /****************************************************************
1971  _spoolss_ClosePrinter
1972 ****************************************************************/
1973
1974 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1975                              struct spoolss_ClosePrinter *r)
1976 {
1977         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1978
1979         if (Printer && Printer->document_started) {
1980                 struct spoolss_EndDocPrinter e;
1981
1982                 e.in.handle = r->in.handle;
1983
1984                 _spoolss_EndDocPrinter(p, &e);
1985         }
1986
1987         if (!close_printer_handle(p, r->in.handle))
1988                 return WERR_BADFID;
1989
1990         /* clear the returned printer handle.  Observed behavior
1991            from Win2k server.  Don't think this really matters.
1992            Previous code just copied the value of the closed
1993            handle.    --jerry */
1994
1995         ZERO_STRUCTP(r->out.handle);
1996
1997         return WERR_OK;
1998 }
1999
2000 /****************************************************************
2001  _spoolss_DeletePrinter
2002 ****************************************************************/
2003
2004 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2005                               struct spoolss_DeletePrinter *r)
2006 {
2007         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2008         WERROR result;
2009         int snum;
2010
2011         if (Printer && Printer->document_started) {
2012                 struct spoolss_EndDocPrinter e;
2013
2014                 e.in.handle = r->in.handle;
2015
2016                 _spoolss_EndDocPrinter(p, &e);
2017         }
2018
2019         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2020                 winreg_delete_printer_key_internal(p->mem_ctx,
2021                                           get_session_info_system(),
2022                                           p->msg_ctx,
2023                                           lp_const_servicename(snum),
2024                                           "");
2025         }
2026
2027         result = delete_printer_handle(p, r->in.handle);
2028
2029         return result;
2030 }
2031
2032 /*******************************************************************
2033  * static function to lookup the version id corresponding to an
2034  * long architecture string
2035  ******************************************************************/
2036
2037 static const struct print_architecture_table_node archi_table[]= {
2038
2039         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2040         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2041         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2042         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2043         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2044         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2045         {"Windows x64",          SPL_ARCH_X64,          3 },
2046         {NULL,                   "",            -1 }
2047 };
2048
2049 static int get_version_id(const char *arch)
2050 {
2051         int i;
2052
2053         for (i=0; archi_table[i].long_archi != NULL; i++)
2054         {
2055                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2056                         return (archi_table[i].version);
2057         }
2058
2059         return -1;
2060 }
2061
2062 /****************************************************************
2063  _spoolss_DeletePrinterDriver
2064 ****************************************************************/
2065
2066 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2067                                     struct spoolss_DeletePrinterDriver *r)
2068 {
2069
2070         struct spoolss_DriverInfo8 *info = NULL;
2071         struct spoolss_DriverInfo8 *info_win2k = NULL;
2072         int                             version;
2073         WERROR                          status;
2074         struct dcerpc_binding_handle *b;
2075         TALLOC_CTX *tmp_ctx = NULL;
2076
2077         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2078            and not a printer admin, then fail */
2079
2080         if ( (p->session_info->unix_token->uid != sec_initial_uid())
2081              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2082                 && !token_contains_name_in_list(
2083                         uidtoname(p->session_info->unix_token->uid),
2084                         p->session_info->info->domain_name,
2085                         NULL,
2086                         p->session_info->security_token,
2087                         lp_printer_admin(-1)) )
2088         {
2089                 return WERR_ACCESS_DENIED;
2090         }
2091
2092         /* check that we have a valid driver name first */
2093
2094         if ((version = get_version_id(r->in.architecture)) == -1) {
2095                 return WERR_INVALID_ENVIRONMENT;
2096         }
2097
2098         tmp_ctx = talloc_new(p->mem_ctx);
2099         if (!tmp_ctx) {
2100                 return WERR_NOMEM;
2101         }
2102
2103         status = winreg_printer_binding_handle(tmp_ctx,
2104                                                get_session_info_system(),
2105                                                p->msg_ctx,
2106                                                &b);
2107         if (!W_ERROR_IS_OK(status)) {
2108                 goto done;
2109         }
2110
2111         status = winreg_get_driver(tmp_ctx, b,
2112                                    r->in.architecture, r->in.driver,
2113                                    version, &info);
2114         if (!W_ERROR_IS_OK(status)) {
2115                 /* try for Win2k driver if "Windows NT x86" */
2116
2117                 if ( version == 2 ) {
2118                         version = 3;
2119
2120                         status = winreg_get_driver(tmp_ctx, b,
2121                                                    r->in.architecture,
2122                                                    r->in.driver,
2123                                                    version, &info);
2124                         if (!W_ERROR_IS_OK(status)) {
2125                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2126                                 goto done;
2127                         }
2128                 }
2129                 /* otherwise it was a failure */
2130                 else {
2131                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2132                         goto done;
2133                 }
2134
2135         }
2136
2137         if (printer_driver_in_use(tmp_ctx,
2138                                   b,
2139                                   info)) {
2140                 status = WERR_PRINTER_DRIVER_IN_USE;
2141                 goto done;
2142         }
2143
2144         if (version == 2) {
2145                 status = winreg_get_driver(tmp_ctx, b,
2146                                            r->in.architecture,
2147                                            r->in.driver, 3, &info_win2k);
2148                 if (W_ERROR_IS_OK(status)) {
2149                         /* if we get to here, we now have 2 driver info structures to remove */
2150                         /* remove the Win2k driver first*/
2151
2152                         status = winreg_del_driver(tmp_ctx, b,
2153                                                    info_win2k, 3);
2154                         talloc_free(info_win2k);
2155
2156                         /* this should not have failed---if it did, report to client */
2157                         if (!W_ERROR_IS_OK(status)) {
2158                                 goto done;
2159                         }
2160                 }
2161         }
2162
2163         status = winreg_del_driver(tmp_ctx, b,
2164                                    info, version);
2165
2166 done:
2167         talloc_free(tmp_ctx);
2168
2169         return status;
2170 }
2171
2172 /****************************************************************
2173  _spoolss_DeletePrinterDriverEx
2174 ****************************************************************/
2175
2176 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2177                                       struct spoolss_DeletePrinterDriverEx *r)
2178 {
2179         struct spoolss_DriverInfo8      *info = NULL;
2180         struct spoolss_DriverInfo8      *info_win2k = NULL;
2181         int                             version;
2182         bool                            delete_files;
2183         WERROR                          status;
2184         struct dcerpc_binding_handle *b;
2185         TALLOC_CTX *tmp_ctx = NULL;
2186
2187         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2188            and not a printer admin, then fail */
2189
2190         if ( (p->session_info->unix_token->uid != sec_initial_uid())
2191                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2192                 && !token_contains_name_in_list(
2193                         uidtoname(p->session_info->unix_token->uid),
2194                         p->session_info->info->domain_name,
2195                         NULL,
2196                         p->session_info->security_token, lp_printer_admin(-1)) )
2197         {
2198                 return WERR_ACCESS_DENIED;
2199         }
2200
2201         /* check that we have a valid driver name first */
2202         if ((version = get_version_id(r->in.architecture)) == -1) {
2203                 /* this is what NT returns */
2204                 return WERR_INVALID_ENVIRONMENT;
2205         }
2206
2207         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) {
2208                 version = r->in.version;
2209         }
2210
2211         tmp_ctx = talloc_new(p->mem_ctx);
2212         if (!tmp_ctx) {
2213                 return WERR_NOMEM;
2214         }
2215
2216         status = winreg_printer_binding_handle(tmp_ctx,
2217                                                get_session_info_system(),
2218                                                p->msg_ctx,
2219                                                &b);
2220         if (!W_ERROR_IS_OK(status)) {
2221                 goto done;
2222         }
2223
2224         status = winreg_get_driver(tmp_ctx, b,
2225                                    r->in.architecture,
2226                                    r->in.driver,
2227                                    version,
2228                                    &info);
2229         if (!W_ERROR_IS_OK(status)) {
2230                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2231
2232                 /*
2233                  * if the client asked for a specific version,
2234                  * or this is something other than Windows NT x86,
2235                  * then we've failed
2236                  */
2237
2238                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2239                         goto done;
2240
2241                 /* try for Win2k driver if "Windows NT x86" */
2242
2243                 version = 3;
2244                 status = winreg_get_driver(tmp_ctx, b,
2245                                            r->in.architecture,
2246                                            r->in.driver,
2247                                            version, &info);
2248                 if (!W_ERROR_IS_OK(status)) {
2249                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2250                         goto done;
2251                 }
2252         }
2253
2254         if (printer_driver_in_use(tmp_ctx,
2255                                   b,
2256                                   info)) {
2257                 status = WERR_PRINTER_DRIVER_IN_USE;
2258                 goto done;
2259         }
2260
2261         /*
2262          * we have a couple of cases to consider.
2263          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2264          *     then the delete should fail if **any** files overlap with
2265          *     other drivers
2266          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2267          *     non-overlapping files
2268          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2269          *     is set, the do not delete any files
2270          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2271          */
2272
2273         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2274
2275         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2276
2277         if (delete_files &&
2278             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2279             printer_driver_files_in_use(tmp_ctx,
2280                                         b,
2281                                         info)) {
2282                 /* no idea of the correct error here */
2283                 status = WERR_ACCESS_DENIED;
2284                 goto done;
2285         }
2286
2287
2288         /* also check for W32X86/3 if necessary; maybe we already have? */
2289
2290         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2291                 status = winreg_get_driver(tmp_ctx, b,
2292                                            r->in.architecture,
2293                                            r->in.driver, 3, &info_win2k);
2294                 if (W_ERROR_IS_OK(status)) {
2295
2296                         if (delete_files &&
2297                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2298                             printer_driver_files_in_use(info,
2299                                                         b,
2300                                                         info_win2k)) {
2301                                 /* no idea of the correct error here */
2302                                 talloc_free(info_win2k);
2303                                 status = WERR_ACCESS_DENIED;
2304                                 goto done;
2305                         }
2306
2307                         /* if we get to here, we now have 2 driver info structures to remove */
2308                         /* remove the Win2k driver first*/
2309
2310                         status = winreg_del_driver(tmp_ctx, b,
2311                                                    info_win2k,
2312                                                    3);
2313
2314                         /* this should not have failed---if it did, report to client */
2315
2316                         if (!W_ERROR_IS_OK(status)) {
2317                                 goto done;
2318                         }
2319
2320                         /*
2321                          * now delete any associated files if delete_files is
2322                          * true. Even if this part failes, we return succes
2323                          * because the driver doesn not exist any more
2324                          */
2325                         if (delete_files) {
2326                                 delete_driver_files(get_session_info_system(),
2327                                                     info_win2k);
2328                         }
2329                 }
2330         }
2331
2332         status = winreg_del_driver(tmp_ctx, b,
2333                                    info,
2334                                    version);
2335         if (!W_ERROR_IS_OK(status)) {
2336                 goto done;
2337         }
2338
2339         /*
2340          * now delete any associated files if delete_files is
2341          * true. Even if this part failes, we return succes
2342          * because the driver doesn not exist any more
2343          */
2344         if (delete_files) {
2345                 delete_driver_files(get_session_info_system(), info);
2346         }
2347
2348 done:
2349         talloc_free(tmp_ctx);
2350         return status;
2351 }
2352
2353
2354 /********************************************************************
2355  GetPrinterData on a printer server Handle.
2356 ********************************************************************/
2357
2358 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2359                                             const char *value,
2360                                             enum winreg_Type *type,
2361                                             union spoolss_PrinterData *data)
2362 {
2363         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2364
2365         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2366                 *type = REG_DWORD;
2367                 data->value = 0x00;
2368                 return WERR_OK;
2369         }
2370
2371         if (!strcasecmp_m(value, "BeepEnabled")) {
2372                 *type = REG_DWORD;
2373                 data->value = 0x00;
2374                 return WERR_OK;
2375         }
2376
2377         if (!strcasecmp_m(value, "EventLog")) {
2378                 *type = REG_DWORD;
2379                 /* formally was 0x1b */
2380                 data->value = 0x00;
2381                 return WERR_OK;
2382         }
2383
2384         if (!strcasecmp_m(value, "NetPopup")) {
2385                 *type = REG_DWORD;
2386                 data->value = 0x00;
2387                 return WERR_OK;
2388         }
2389
2390         if (!strcasecmp_m(value, "MajorVersion")) {
2391                 *type = REG_DWORD;
2392
2393                 /* Windows NT 4.0 seems to not allow uploading of drivers
2394                    to a server that reports 0x3 as the MajorVersion.
2395                    need to investigate more how Win2k gets around this .
2396                    -- jerry */
2397
2398                 if (RA_WINNT == get_remote_arch()) {
2399                         data->value = 0x02;
2400                 } else {
2401                         data->value = 0x03;
2402                 }
2403
2404                 return WERR_OK;
2405         }
2406
2407         if (!strcasecmp_m(value, "MinorVersion")) {
2408                 *type = REG_DWORD;
2409                 data->value = 0x00;
2410                 return WERR_OK;
2411         }
2412
2413         /* REG_BINARY
2414          *  uint32_t size        = 0x114
2415          *  uint32_t major       = 5
2416          *  uint32_t minor       = [0|1]
2417          *  uint32_t build       = [2195|2600]
2418          *  extra unicode string = e.g. "Service Pack 3"
2419          */
2420         if (!strcasecmp_m(value, "OSVersion")) {
2421                 DATA_BLOB blob;
2422                 enum ndr_err_code ndr_err;
2423                 struct spoolss_OSVersion os;
2424
2425                 os.major                = 5;    /* Windows 2000 == 5.0 */
2426                 os.minor                = 0;
2427                 os.build                = 2195; /* build */
2428                 os.extra_string         = "";   /* leave extra string empty */
2429
2430                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2431                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2432                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2433                         return WERR_GENERAL_FAILURE;
2434                 }
2435
2436                 *type = REG_BINARY;
2437                 data->binary = blob;
2438
2439                 return WERR_OK;
2440         }
2441
2442
2443         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2444                 *type = REG_SZ;
2445
2446                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2447                 W_ERROR_HAVE_NO_MEMORY(data->string);
2448
2449                 return WERR_OK;
2450         }
2451
2452         if (!strcasecmp_m(value, "Architecture")) {
2453                 *type = REG_SZ;
2454                 data->string = talloc_strdup(mem_ctx,
2455                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2456                 W_ERROR_HAVE_NO_MEMORY(data->string);
2457
2458                 return WERR_OK;
2459         }
2460
2461         if (!strcasecmp_m(value, "DsPresent")) {
2462                 *type = REG_DWORD;
2463
2464                 /* only show the publish check box if we are a
2465                    member of a AD domain */
2466
2467                 if (lp_security() == SEC_ADS) {
2468                         data->value = 0x01;
2469                 } else {
2470                         data->value = 0x00;
2471                 }
2472                 return WERR_OK;
2473         }
2474
2475         if (!strcasecmp_m(value, "DNSMachineName")) {
2476                 const char *hostname = get_mydnsfullname();
2477
2478                 if (!hostname) {
2479                         return WERR_BADFILE;
2480                 }
2481
2482                 *type = REG_SZ;
2483                 data->string = talloc_strdup(mem_ctx, hostname);
2484                 W_ERROR_HAVE_NO_MEMORY(data->string);
2485
2486                 return WERR_OK;
2487         }
2488
2489         *type = REG_NONE;
2490
2491         return WERR_INVALID_PARAM;
2492 }
2493
2494 /****************************************************************
2495  _spoolss_GetPrinterData
2496 ****************************************************************/
2497
2498 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2499                                struct spoolss_GetPrinterData *r)
2500 {
2501         struct spoolss_GetPrinterDataEx r2;
2502
2503         r2.in.handle            = r->in.handle;
2504         r2.in.key_name          = "PrinterDriverData";
2505         r2.in.value_name        = r->in.value_name;
2506         r2.in.offered           = r->in.offered;
2507         r2.out.type             = r->out.type;
2508         r2.out.data             = r->out.data;
2509         r2.out.needed           = r->out.needed;
2510
2511         return _spoolss_GetPrinterDataEx(p, &r2);
2512 }
2513
2514 /*********************************************************
2515  Connect to the client machine.
2516 **********************************************************/
2517
2518 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2519                         struct sockaddr_storage *client_ss, const char *remote_machine)
2520 {
2521         NTSTATUS ret;
2522         struct cli_state *the_cli;
2523         struct sockaddr_storage rm_addr;
2524         char addr[INET6_ADDRSTRLEN];
2525
2526         if ( is_zero_addr(client_ss) ) {
2527                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2528                         remote_machine));
2529                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2530                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2531                         return false;
2532                 }
2533                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2534         } else {
2535                 rm_addr = *client_ss;
2536                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2537                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2538                         addr));
2539         }
2540
2541         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2542                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2543                         addr));
2544                 return false;
2545         }
2546
2547         /* setup the connection */
2548         ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2549                 &rm_addr, 0, "IPC$", "IPC",
2550                 "", /* username */
2551                 "", /* domain */
2552                 "", /* password */
2553                 0, lp_client_signing());
2554
2555         if ( !NT_STATUS_IS_OK( ret ) ) {
2556                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2557                         remote_machine ));
2558                 return false;
2559         }
2560
2561         if ( cli_state_protocol(the_cli) != PROTOCOL_NT1 ) {
2562                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2563                 cli_shutdown(the_cli);
2564                 return false;
2565         }
2566
2567         /*
2568          * Ok - we have an anonymous connection to the IPC$ share.
2569          * Now start the NT Domain stuff :-).
2570          */
2571
2572         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2573         if (!NT_STATUS_IS_OK(ret)) {
2574                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2575                         remote_machine, nt_errstr(ret)));
2576                 cli_shutdown(the_cli);
2577                 return false;
2578         }
2579
2580         return true;
2581 }
2582
2583 /***************************************************************************
2584  Connect to the client.
2585 ****************************************************************************/
2586
2587 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2588                                         uint32_t localprinter,
2589                                         enum winreg_Type type,
2590                                         struct policy_handle *handle,
2591                                         struct notify_back_channel **_chan,
2592                                         struct sockaddr_storage *client_ss,
2593                                         struct messaging_context *msg_ctx)
2594 {
2595         WERROR result;
2596         NTSTATUS status;
2597         struct notify_back_channel *chan;
2598
2599         for (chan = back_channels; chan; chan = chan->next) {
2600                 if (memcmp(&chan->client_address, client_ss,
2601                            sizeof(struct sockaddr_storage)) == 0) {
2602                         break;
2603                 }
2604         }
2605
2606         /*
2607          * If it's the first connection, contact the client
2608          * and connect to the IPC$ share anonymously
2609          */
2610         if (!chan) {
2611                 fstring unix_printer;
2612
2613                 /* the +2 is to strip the leading 2 backslashs */
2614                 fstrcpy(unix_printer, printer + 2);
2615
2616                 chan = talloc_zero(back_channels, struct notify_back_channel);
2617                 if (!chan) {
2618                         return false;
2619                 }
2620                 chan->client_address = *client_ss;
2621
2622                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2623                         TALLOC_FREE(chan);
2624                         return false;
2625                 }
2626
2627                 DLIST_ADD(back_channels, chan);
2628
2629                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2630                                    receive_notify2_message_list);
2631         }
2632
2633         if (chan->cli_pipe == NULL ||
2634             chan->cli_pipe->binding_handle == NULL) {
2635                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2636                         "NULL %s for printer %s\n",
2637                         chan->cli_pipe == NULL ?
2638                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2639                         printer));
2640                 return false;
2641         }
2642
2643         /*
2644          * Tell the specific printing tdb we want messages for this printer
2645          * by registering our PID.
2646          */
2647
2648         if (!print_notify_register_pid(snum)) {
2649                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2650                           printer));
2651         }
2652
2653         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2654                                                  talloc_tos(),
2655                                                  printer,
2656                                                  localprinter,
2657                                                  type,
2658                                                  0,
2659                                                  NULL,
2660                                                  handle,
2661                                                  &result);
2662         if (!NT_STATUS_IS_OK(status)) {
2663                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2664                 result = ntstatus_to_werror(status);
2665         } else if (!W_ERROR_IS_OK(result)) {
2666                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2667         }
2668
2669         chan->active_connections++;
2670         *_chan = chan;
2671
2672         return (W_ERROR_IS_OK(result));
2673 }
2674
2675 /****************************************************************
2676  ****************************************************************/
2677
2678 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2679                                                              const struct spoolss_NotifyOption *r)
2680 {
2681         struct spoolss_NotifyOption *option;
2682         uint32_t i,k;
2683
2684         if (!r) {
2685                 return NULL;
2686         }
2687
2688         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2689         if (!option) {
2690                 return NULL;
2691         }
2692
2693         *option = *r;
2694
2695         if (!option->count) {
2696                 return option;
2697         }
2698
2699         option->types = talloc_zero_array(option,
2700                 struct spoolss_NotifyOptionType, option->count);
2701         if (!option->types) {
2702                 talloc_free(option);
2703                 return NULL;
2704         }
2705
2706         for (i=0; i < option->count; i++) {
2707                 option->types[i] = r->types[i];
2708
2709                 if (option->types[i].count) {
2710                         option->types[i].fields = talloc_zero_array(option,
2711                                 union spoolss_Field, option->types[i].count);
2712                         if (!option->types[i].fields) {
2713                                 talloc_free(option);
2714                                 return NULL;
2715                         }
2716                         for (k=0; k<option->types[i].count; k++) {
2717                                 option->types[i].fields[k] =
2718                                         r->types[i].fields[k];
2719                         }
2720                 }
2721         }
2722
2723         return option;
2724 }
2725
2726 /****************************************************************
2727  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2728  *
2729  * before replying OK: status=0 a rpc call is made to the workstation
2730  * asking ReplyOpenPrinter
2731  *
2732  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2733  * called from api_spoolss_rffpcnex
2734 ****************************************************************/
2735
2736 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2737                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2738 {
2739         int snum = -1;
2740         struct spoolss_NotifyOption *option = r->in.notify_options;
2741         struct sockaddr_storage client_ss;
2742         socklen_t client_len;
2743
2744         /* store the notify value in the printer struct */
2745
2746         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2747
2748         if (!Printer) {
2749                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2750                         "Invalid handle (%s:%u:%u).\n",
2751                         OUR_HANDLE(r->in.handle)));
2752                 return WERR_BADFID;
2753         }
2754
2755         Printer->notify.flags           = r->in.flags;
2756         Printer->notify.options         = r->in.options;
2757         Printer->notify.printerlocal    = r->in.printer_local;
2758         Printer->notify.msg_ctx         = p->msg_ctx;
2759
2760         TALLOC_FREE(Printer->notify.option);
2761         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2762
2763         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2764
2765         /* Connect to the client machine and send a ReplyOpenPrinter */
2766
2767         if ( Printer->printer_type == SPLHND_SERVER)
2768                 snum = -1;
2769         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2770                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2771                 return WERR_BADFID;
2772
2773         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2774                   "remote_address is %s\n",
2775                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2776
2777         if (!lp_print_notify_backchannel(snum)) {
2778                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2779                         "backchannel disabled\n"));
2780                 return WERR_SERVER_UNAVAILABLE;
2781         }
2782
2783         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2784                                                   (struct sockaddr *) &client_ss,
2785                                                   sizeof(struct sockaddr_storage));
2786         if (client_len < 0) {
2787                 return WERR_NOMEM;
2788         }
2789
2790         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2791                                         Printer->notify.printerlocal, REG_SZ,
2792                                         &Printer->notify.cli_hnd,
2793                                         &Printer->notify.cli_chan,
2794                                         &client_ss, p->msg_ctx)) {
2795                 return WERR_SERVER_UNAVAILABLE;
2796         }
2797
2798         return WERR_OK;
2799 }
2800
2801 /*******************************************************************
2802  * fill a notify_info_data with the servername
2803  ********************************************************************/
2804
2805 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2806                                        int snum,
2807                                        struct spoolss_Notify *data,
2808                                        print_queue_struct *queue,
2809                                        struct spoolss_PrinterInfo2 *pinfo2,
2810                                        TALLOC_CTX *mem_ctx)
2811 {
2812         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2813 }
2814
2815 /*******************************************************************
2816  * fill a notify_info_data with the printername (not including the servername).
2817  ********************************************************************/
2818
2819 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2820                                         int snum,
2821                                         struct spoolss_Notify *data,
2822                                         print_queue_struct *queue,
2823                                         struct spoolss_PrinterInfo2 *pinfo2,
2824                                         TALLOC_CTX *mem_ctx)
2825 {
2826         /* the notify name should not contain the \\server\ part */
2827         const char *p = strrchr(pinfo2->printername, '\\');
2828
2829         if (!p) {
2830                 p = pinfo2->printername;
2831         } else {
2832                 p++;
2833         }
2834
2835         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2836 }
2837
2838 /*******************************************************************
2839  * fill a notify_info_data with the servicename
2840  ********************************************************************/
2841
2842 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2843                                       int snum,
2844                                       struct spoolss_Notify *data,
2845                                       print_queue_struct *queue,
2846                                       struct spoolss_PrinterInfo2 *pinfo2,
2847                                       TALLOC_CTX *mem_ctx)
2848 {
2849         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2850 }
2851
2852 /*******************************************************************
2853  * fill a notify_info_data with the port name
2854  ********************************************************************/
2855
2856 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2857                                      int snum,
2858                                      struct spoolss_Notify *data,
2859                                      print_queue_struct *queue,
2860                                      struct spoolss_PrinterInfo2 *pinfo2,
2861                                      TALLOC_CTX *mem_ctx)
2862 {
2863         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2864 }
2865
2866 /*******************************************************************
2867  * fill a notify_info_data with the printername
2868  * but it doesn't exist, have to see what to do
2869  ********************************************************************/
2870
2871 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2872                                        int snum,
2873                                        struct spoolss_Notify *data,
2874                                        print_queue_struct *queue,
2875                                        struct spoolss_PrinterInfo2 *pinfo2,
2876                                        TALLOC_CTX *mem_ctx)
2877 {
2878         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2879 }
2880
2881 /*******************************************************************
2882  * fill a notify_info_data with the comment
2883  ********************************************************************/
2884
2885 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2886                                    int snum,
2887                                    struct spoolss_Notify *data,
2888                                    print_queue_struct *queue,
2889                                    struct spoolss_PrinterInfo2 *pinfo2,
2890                                    TALLOC_CTX *mem_ctx)
2891 {
2892         const char *p;
2893
2894         if (*pinfo2->comment == '\0') {
2895                 p = lp_comment(snum);
2896         } else {
2897                 p = pinfo2->comment;
2898         }
2899
2900         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2901 }
2902
2903 /*******************************************************************
2904  * fill a notify_info_data with the comment
2905  * location = "Room 1, floor 2, building 3"
2906  ********************************************************************/
2907
2908 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2909                                     int snum,
2910                                     struct spoolss_Notify *data,
2911                                     print_queue_struct *queue,
2912                                     struct spoolss_PrinterInfo2 *pinfo2,
2913                                     TALLOC_CTX *mem_ctx)
2914 {
2915         const char *loc = pinfo2->location;
2916         NTSTATUS status;
2917
2918         status = printer_list_get_printer(mem_ctx,
2919                                           pinfo2->sharename,
2920                                           NULL,
2921                                           &loc,
2922                                           NULL);
2923         if (NT_STATUS_IS_OK(status)) {
2924                 if (loc == NULL) {
2925                         loc = pinfo2->location;
2926                 }
2927         }
2928
2929         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2930 }
2931
2932 /*******************************************************************
2933  * fill a notify_info_data with the device mode
2934  * jfm:xxxx don't to it for know but that's a real problem !!!
2935  ********************************************************************/
2936
2937 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2938                                    int snum,
2939                                    struct spoolss_Notify *data,
2940                                    print_queue_struct *queue,
2941                                    struct spoolss_PrinterInfo2 *pinfo2,
2942                                    TALLOC_CTX *mem_ctx)
2943 {
2944         /* for a dummy implementation we have to zero the fields */
2945         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2946 }
2947
2948 /*******************************************************************
2949  * fill a notify_info_data with the separator file name
2950  ********************************************************************/
2951
2952 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2953                                    int snum,
2954                                    struct spoolss_Notify *data,
2955                                    print_queue_struct *queue,
2956                                    struct spoolss_PrinterInfo2 *pinfo2,
2957                                    TALLOC_CTX *mem_ctx)
2958 {
2959         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2960 }
2961
2962 /*******************************************************************
2963  * fill a notify_info_data with the print processor
2964  * jfm:xxxx return always winprint to indicate we don't do anything to it
2965  ********************************************************************/
2966
2967 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2968                                            int snum,
2969                                            struct spoolss_Notify *data,
2970                                            print_queue_struct *queue,
2971                                            struct spoolss_PrinterInfo2 *pinfo2,
2972                                            TALLOC_CTX *mem_ctx)
2973 {
2974         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2975 }
2976
2977 /*******************************************************************
2978  * fill a notify_info_data with the print processor options
2979  * jfm:xxxx send an empty string
2980  ********************************************************************/
2981
2982 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2983                                       int snum,
2984                                       struct spoolss_Notify *data,
2985                                       print_queue_struct *queue,
2986                                       struct spoolss_PrinterInfo2 *pinfo2,
2987                                       TALLOC_CTX *mem_ctx)
2988 {
2989         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2990 }
2991
2992 /*******************************************************************
2993  * fill a notify_info_data with the data type
2994  * jfm:xxxx always send RAW as data type
2995  ********************************************************************/
2996
2997 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2998                                     int snum,
2999                                     struct spoolss_Notify *data,
3000                                     print_queue_struct *queue,
3001                                     struct spoolss_PrinterInfo2 *pinfo2,
3002                                     TALLOC_CTX *mem_ctx)
3003 {
3004         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
3005 }
3006
3007 /*******************************************************************
3008  * fill a notify_info_data with the security descriptor
3009  * jfm:xxxx send an null pointer to say no security desc
3010  * have to implement security before !
3011  ********************************************************************/
3012
3013 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
3014                                          int snum,
3015                                          struct spoolss_Notify *data,
3016                                          print_queue_struct *queue,
3017                                          struct spoolss_PrinterInfo2 *pinfo2,
3018                                          TALLOC_CTX *mem_ctx)
3019 {
3020         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
3021 }
3022
3023 /*******************************************************************
3024  * fill a notify_info_data with the attributes
3025  * jfm:xxxx a samba printer is always shared
3026  ********************************************************************/
3027
3028 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
3029                                       int snum,
3030                                       struct spoolss_Notify *data,
3031                                       print_queue_struct *queue,
3032                                       struct spoolss_PrinterInfo2 *pinfo2,
3033                                       TALLOC_CTX *mem_ctx)
3034 {
3035         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3036 }
3037
3038 /*******************************************************************
3039  * fill a notify_info_data with the priority
3040  ********************************************************************/
3041
3042 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3043                                     int snum,
3044                                     struct spoolss_Notify *data,
3045                                     print_queue_struct *queue,
3046                                     struct spoolss_PrinterInfo2 *pinfo2,
3047                                     TALLOC_CTX *mem_ctx)
3048 {
3049         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3050 }
3051
3052 /*******************************************************************
3053  * fill a notify_info_data with the default priority
3054  ********************************************************************/
3055
3056 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3057                                             int snum,
3058                                             struct spoolss_Notify *data,
3059                                             print_queue_struct *queue,
3060                                             struct spoolss_PrinterInfo2 *pinfo2,
3061                                             TALLOC_CTX *mem_ctx)
3062 {
3063         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3064 }
3065
3066 /*******************************************************************
3067  * fill a notify_info_data with the start time
3068  ********************************************************************/
3069
3070 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3071                                       int snum,
3072                                       struct spoolss_Notify *data,
3073                                       print_queue_struct *queue,
3074                                       struct spoolss_PrinterInfo2 *pinfo2,
3075                                       TALLOC_CTX *mem_ctx)
3076 {
3077         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3078 }
3079
3080 /*******************************************************************
3081  * fill a notify_info_data with the until time
3082  ********************************************************************/
3083
3084 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3085                                       int snum,
3086                                       struct spoolss_Notify *data,
3087                                       print_queue_struct *queue,
3088                                       struct spoolss_PrinterInfo2 *pinfo2,
3089                                       TALLOC_CTX *mem_ctx)
3090 {
3091         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3092 }
3093
3094 /*******************************************************************
3095  * fill a notify_info_data with the status
3096  ********************************************************************/
3097
3098 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3099                                   int snum,
3100                                   struct spoolss_Notify *data,
3101                                   print_queue_struct *queue,
3102                                   struct spoolss_PrinterInfo2 *pinfo2,
3103                                   TALLOC_CTX *mem_ctx)
3104 {
3105         print_status_struct status;
3106
3107         print_queue_length(msg_ctx, snum, &status);
3108         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3109 }
3110
3111 /*******************************************************************
3112  * fill a notify_info_data with the number of jobs queued
3113  ********************************************************************/
3114
3115 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3116                                  int snum,
3117                                  struct spoolss_Notify *data,
3118                                  print_queue_struct *queue,
3119                                  struct spoolss_PrinterInfo2 *pinfo2,
3120                                  TALLOC_CTX *mem_ctx)
3121 {
3122         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3123                 data, print_queue_length(msg_ctx, snum, NULL));
3124 }
3125
3126 /*******************************************************************
3127  * fill a notify_info_data with the average ppm
3128  ********************************************************************/
3129
3130 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3131                                        int snum,
3132                                        struct spoolss_Notify *data,
3133                                        print_queue_struct *queue,
3134                                        struct spoolss_PrinterInfo2 *pinfo2,
3135                                        TALLOC_CTX *mem_ctx)
3136 {
3137         /* always respond 8 pages per minutes */
3138         /* a little hard ! */
3139         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3140 }
3141
3142 /*******************************************************************
3143  * fill a notify_info_data with username
3144  ********************************************************************/
3145
3146 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3147                                     int snum,
3148                                     struct spoolss_Notify *data,
3149                                     print_queue_struct *queue,
3150                                     struct spoolss_PrinterInfo2 *pinfo2,
3151                                     TALLOC_CTX *mem_ctx)
3152 {
3153         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3154 }
3155
3156 /*******************************************************************
3157  * fill a notify_info_data with job status
3158  ********************************************************************/
3159
3160 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3161                                       int snum,
3162                                       struct spoolss_Notify *data,
3163                                       print_queue_struct *queue,
3164                                       struct spoolss_PrinterInfo2 *pinfo2,
3165                                       TALLOC_CTX *mem_ctx)
3166 {
3167         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3168 }
3169
3170 /*******************************************************************
3171  * fill a notify_info_data with job name
3172  ********************************************************************/
3173
3174 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3175                                     int snum,
3176                                     struct spoolss_Notify *data,
3177                                     print_queue_struct *queue,
3178                                     struct spoolss_PrinterInfo2 *pinfo2,
3179                                     TALLOC_CTX *mem_ctx)
3180 {
3181         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3182 }
3183
3184 /*******************************************************************
3185  * fill a notify_info_data with job status
3186  ********************************************************************/
3187
3188 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3189                                              int snum,
3190                                              struct spoolss_Notify *data,
3191                                              print_queue_struct *queue,
3192                                              struct spoolss_PrinterInfo2 *pinfo2,
3193                                              TALLOC_CTX *mem_ctx)
3194 {
3195         /*
3196          * Now we're returning job status codes we just return a "" here. JRA.
3197          */
3198
3199         const char *p = "";
3200
3201 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3202         p = "unknown";
3203
3204         switch (queue->status) {
3205         case LPQ_QUEUED:
3206                 p = "Queued";
3207                 break;
3208         case LPQ_PAUSED:
3209                 p = "";    /* NT provides the paused string */
3210                 break;
3211         case LPQ_SPOOLING:
3212                 p = "Spooling";
3213                 break;
3214         case LPQ_PRINTING:
3215                 p = "Printing";
3216                 break;
3217         }
3218 #endif /* NO LONGER NEEDED. */
3219
3220         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3221 }
3222
3223 /*******************************************************************
3224  * fill a notify_info_data with job time
3225  ********************************************************************/
3226
3227 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3228                                     int snum,
3229                                     struct spoolss_Notify *data,
3230                                     print_queue_struct *queue,
3231                                     struct spoolss_PrinterInfo2 *pinfo2,
3232                                     TALLOC_CTX *mem_ctx)
3233 {
3234         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3235 }
3236
3237 /*******************************************************************
3238  * fill a notify_info_data with job size
3239  ********************************************************************/
3240
3241 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3242                                     int snum,
3243                                     struct spoolss_Notify *data,
3244                                     print_queue_struct *queue,
3245                                     struct spoolss_PrinterInfo2 *pinfo2,
3246                                     TALLOC_CTX *mem_ctx)
3247 {
3248         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3249 }
3250
3251 /*******************************************************************
3252  * fill a notify_info_data with page info
3253  ********************************************************************/
3254 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3255                                        int snum,
3256                                 struct spoolss_Notify *data,
3257                                 print_queue_struct *queue,
3258                                 struct spoolss_PrinterInfo2 *pinfo2,
3259                                 TALLOC_CTX *mem_ctx)
3260 {
3261         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3262 }
3263
3264 /*******************************************************************
3265  * fill a notify_info_data with pages printed info.
3266  ********************************************************************/
3267 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3268                                          int snum,
3269                                 struct spoolss_Notify *data,
3270                                 print_queue_struct *queue,
3271                                 struct spoolss_PrinterInfo2 *pinfo2,
3272                                 TALLOC_CTX *mem_ctx)
3273 {
3274         /* Add code when back-end tracks this */
3275         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3276 }
3277
3278 /*******************************************************************
3279  Fill a notify_info_data with job position.
3280  ********************************************************************/
3281
3282 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3283                                         int snum,
3284                                         struct spoolss_Notify *data,
3285                                         print_queue_struct *queue,
3286                                         struct spoolss_PrinterInfo2 *pinfo2,
3287                                         TALLOC_CTX *mem_ctx)
3288 {
3289         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3290 }
3291
3292 /*******************************************************************
3293  Fill a notify_info_data with submitted time.
3294  ********************************************************************/
3295
3296 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3297                                           int snum,
3298                                           struct spoolss_Notify *data,
3299                                           print_queue_struct *queue,
3300                                           struct spoolss_PrinterInfo2 *pinfo2,
3301                                           TALLOC_CTX *mem_ctx)
3302 {
3303         data->data.string.string = NULL;
3304         data->data.string.size = 0;
3305
3306         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3307                                &data->data.string.string,
3308                                &data->data.string.size);
3309
3310 }
3311
3312 struct s_notify_info_data_table
3313 {
3314         enum spoolss_NotifyType type;
3315         uint16_t field;
3316         const char *name;
3317         enum spoolss_NotifyTable variable_type;
3318         void (*fn) (struct messaging_context *msg_ctx,
3319                     int snum, struct spoolss_Notify *data,
3320                     print_queue_struct *queue,
3321                     struct spoolss_PrinterInfo2 *pinfo2,
3322                     TALLOC_CTX *mem_ctx);
3323 };
3324
3325 /* A table describing the various print notification constants and
3326    whether the notification data is a pointer to a variable sized
3327    buffer, a one value uint32_t or a two value uint32_t. */
3328
3329 static const struct s_notify_info_data_table notify_info_data_table[] =
3330 {
3331 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3332 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3333 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3334 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3335 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3336 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3337 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3338 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3339 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3340 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3341 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3342 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3343 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3344 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3345 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3346 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3347 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3348 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3349 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3350 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3351 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3352 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3353 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3354 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3355 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3356 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3357 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3358 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3359 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3360 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3361 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3362 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3363 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3364 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3365 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3366 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3367 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3368 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3369 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3370 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3371 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3372 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3373 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3374 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3375 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3376 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3377 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3378 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3379 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3380 };
3381
3382 /*******************************************************************
3383  Return the variable_type of info_data structure.
3384 ********************************************************************/
3385
3386 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3387                                                                   uint16_t field)
3388 {
3389         int i=0;
3390
3391         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3392                 if ( (notify_info_data_table[i].type == type) &&
3393                      (notify_info_data_table[i].field == field) ) {
3394                         return notify_info_data_table[i].variable_type;
3395                 }
3396         }
3397
3398         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3399
3400         return (enum spoolss_NotifyTable) 0;
3401 }
3402
3403 /****************************************************************************
3404 ****************************************************************************/
3405
3406 static bool search_notify(enum spoolss_NotifyType type,
3407                           uint16_t field,
3408                           int *value)
3409 {
3410         int i;
3411
3412         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3413                 if (notify_info_data_table[i].type == type &&
3414                     notify_info_data_table[i].field == field &&
3415                     notify_info_data_table[i].fn != NULL) {
3416                         *value = i;
3417                         return true;
3418                 }
3419         }
3420
3421         return false;
3422 }
3423
3424 /****************************************************************************
3425 ****************************************************************************/
3426
3427 static void construct_info_data(struct spoolss_Notify *info_data,
3428                                 enum spoolss_NotifyType type,
3429                                 uint16_t field, int id)
3430 {
3431         info_data->type                 = type;
3432         info_data->field.field          = field;
3433         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3434         info_data->job_id               = id;
3435 }
3436
3437 /*******************************************************************
3438  *
3439  * fill a notify_info struct with info asked
3440  *
3441  ********************************************************************/
3442
3443 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3444                                           struct printer_handle *print_hnd,
3445                                           struct spoolss_NotifyInfo *info,
3446                                           struct spoolss_PrinterInfo2 *pinfo2,
3447                                           int snum,
3448                                           const struct spoolss_NotifyOptionType *option_type,
3449                                           uint32_t id,
3450                                           TALLOC_CTX *mem_ctx)
3451 {
3452         int field_num,j;
3453         enum spoolss_NotifyType type;
3454         uint16_t field;
3455
3456         struct spoolss_Notify *current_data;
3457
3458         type = option_type->type;
3459
3460         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3461                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3462                 option_type->count, lp_servicename(snum)));
3463
3464         for(field_num=0; field_num < option_type->count; field_num++) {
3465                 field = option_type->fields[field_num].field;
3466
3467                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3468
3469                 if (!search_notify(type, field, &j) )
3470                         continue;
3471
3472                 info->notifies = talloc_realloc(info, info->notifies,
3473                                                       struct spoolss_Notify,
3474                                                       info->count + 1);
3475                 if (info->notifies == NULL) {
3476                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3477                         return false;
3478                 }
3479
3480                 current_data = &info->notifies[info->count];
3481
3482                 construct_info_data(current_data, type, field, id);
3483
3484                 DEBUG(10, ("construct_notify_printer_info: "
3485                            "calling [%s]  snum=%d  printername=[%s])\n",
3486                            notify_info_data_table[j].name, snum,
3487                            pinfo2->printername));
3488
3489                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3490                                              NULL, pinfo2, mem_ctx);
3491
3492                 info->count++;
3493         }
3494
3495         return true;
3496 }
3497
3498 /*******************************************************************
3499  *
3500  * fill a notify_info struct with info asked
3501  *
3502  ********************************************************************/
3503
3504 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3505                                        print_queue_struct *queue,
3506                                        struct spoolss_NotifyInfo *info,
3507                                        struct spoolss_PrinterInfo2 *pinfo2,
3508                                        int snum,
3509                                        const struct spoolss_NotifyOptionType *option_type,
3510                                        uint32_t id,
3511                                        TALLOC_CTX *mem_ctx)
3512 {
3513         int field_num,j;
3514         enum spoolss_NotifyType type;
3515         uint16_t field;
3516         struct spoolss_Notify *current_data;
3517
3518         DEBUG(4,("construct_notify_jobs_info\n"));
3519
3520         type = option_type->type;
3521
3522         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3523                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3524                 option_type->count));
3525
3526         for(field_num=0; field_num<option_type->count; field_num++) {
3527                 field = option_type->fields[field_num].field;
3528
3529                 if (!search_notify(type, field, &j) )
3530                         continue;
3531
3532                 info->notifies = talloc_realloc(info, info->notifies,
3533                                                       struct spoolss_Notify,
3534                                                       info->count + 1);
3535                 if (info->notifies == NULL) {
3536                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3537                         return false;
3538                 }
3539
3540                 current_data=&(info->notifies[info->count]);
3541
3542                 construct_info_data(current_data, type, field, id);
3543                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3544                                              queue, pinfo2, mem_ctx);
3545                 info->count++;
3546         }
3547
3548         return true;
3549 }
3550
3551 /*
3552  * JFM: The enumeration is not that simple, it's even non obvious.
3553  *
3554  * let's take an example: I want to monitor the PRINTER SERVER for
3555  * the printer's name and the number of jobs currently queued.
3556  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3557  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3558  *
3559  * I have 3 printers on the back of my server.
3560  *
3561  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3562  * structures.
3563  *   Number     Data                    Id
3564  *      1       printer 1 name          1
3565  *      2       printer 1 cjob          1
3566  *      3       printer 2 name          2
3567  *      4       printer 2 cjob          2
3568  *      5       printer 3 name          3
3569  *      6       printer 3 name          3
3570  *
3571  * that's the print server case, the printer case is even worse.
3572  */
3573
3574 /*******************************************************************
3575  *
3576  * enumerate all printers on the printserver
3577  * fill a notify_info struct with info asked
3578  *
3579  ********************************************************************/
3580
3581 static WERROR printserver_notify_info(struct pipes_struct *p,
3582                                       struct policy_handle *hnd,
3583                                       struct spoolss_NotifyInfo *info,
3584                                       TALLOC_CTX *mem_ctx)
3585 {
3586         int snum;
3587         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3588         int n_services=lp_numservices();
3589         int i;
3590         struct spoolss_NotifyOption *option;
3591         struct spoolss_NotifyOptionType option_type;
3592         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3593         WERROR result;
3594
3595         DEBUG(4,("printserver_notify_info\n"));
3596
3597         if (!Printer)
3598                 return WERR_BADFID;
3599
3600         option = Printer->notify.option;
3601
3602         info->version   = 2;
3603         info->notifies  = NULL;
3604         info->count     = 0;
3605
3606         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3607            sending a ffpcn() request first */
3608
3609         if ( !option )
3610                 return WERR_BADFID;
3611
3612         for (i=0; i<option->count; i++) {
3613                 option_type = option->types[i];
3614
3615                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3616                         continue;
3617
3618                 for (snum = 0; snum < n_services; snum++) {
3619                         if (!lp_browseable(snum) ||
3620                             !lp_snum_ok(snum) ||
3621                             !lp_print_ok(snum)) {
3622                                 continue; /* skip */
3623                         }
3624
3625                         /* Maybe we should use the SYSTEM session_info here... */
3626                         result = winreg_get_printer_internal(mem_ctx,
3627                                                     get_session_info_system(),
3628                                                     p->msg_ctx,
3629                                                     lp_servicename(snum),
3630                                                     &pinfo2);
3631                         if (!W_ERROR_IS_OK(result)) {
3632                                 DEBUG(4, ("printserver_notify_info: "
3633                                           "Failed to get printer [%s]\n",
3634                                           lp_servicename(snum)));
3635                                 continue;
3636                         }
3637
3638
3639                         construct_notify_printer_info(p->msg_ctx,
3640                                                       Printer, info,
3641                                                       pinfo2, snum,
3642                                                       &option_type, snum,
3643                                                       mem_ctx);
3644
3645                         TALLOC_FREE(pinfo2);
3646                 }
3647         }
3648
3649 #if 0
3650         /*
3651          * Debugging information, don't delete.
3652          */
3653
3654         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3655         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3656         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3657
3658         for (i=0; i<info->count; i++) {
3659                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3660                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3661                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3662         }
3663 #endif
3664
3665         return WERR_OK;
3666 }
3667
3668 /*******************************************************************
3669  *
3670  * fill a notify_info struct with info asked
3671  *
3672  ********************************************************************/
3673
3674 static WERROR printer_notify_info(struct pipes_struct *p,
3675                                   struct policy_handle *hnd,
3676                                   struct spoolss_NotifyInfo *info,
3677                                   TALLOC_CTX *mem_ctx)
3678 {
3679         int snum;
3680         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3681         int i;
3682         uint32_t id;
3683         struct spoolss_NotifyOption *option;
3684         struct spoolss_NotifyOptionType option_type;
3685         int count,j;
3686         print_queue_struct *queue=NULL;
3687         print_status_struct status;
3688         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3689         WERROR result;
3690
3691         DEBUG(4,("printer_notify_info\n"));
3692
3693         if (!Printer)
3694                 return WERR_BADFID;
3695
3696         option = Printer->notify.option;
3697         id = 0x0;
3698
3699         info->version   = 2;
3700         info->notifies  = NULL;
3701         info->count     = 0;
3702
3703         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3704            sending a ffpcn() request first */
3705
3706         if ( !option )
3707                 return WERR_BADFID;
3708
3709         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3710                 return WERR_BADFID;
3711         }
3712
3713         /* Maybe we should use the SYSTEM session_info here... */
3714         result = winreg_get_printer_internal(mem_ctx,
3715                                     get_session_info_system(),
3716                                     p->msg_ctx,
3717                                     lp_servicename(snum), &pinfo2);
3718         if (!W_ERROR_IS_OK(result)) {
3719                 return WERR_BADFID;
3720         }
3721
3722         /*
3723          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3724          * correct servername.
3725          */
3726         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3727         if (pinfo2->servername == NULL) {
3728                 return WERR_NOMEM;
3729         }
3730
3731         for (i=0; i<option->count; i++) {
3732                 option_type = option->types[i];
3733
3734                 switch (option_type.type) {
3735                 case PRINTER_NOTIFY_TYPE:
3736                         if (construct_notify_printer_info(p->msg_ctx,
3737                                                           Printer, info,
3738                                                           pinfo2, snum,
3739                                                           &option_type, id,
3740                                                           mem_ctx)) {
3741                                 id--;
3742                         }
3743                         break;
3744
3745                 case JOB_NOTIFY_TYPE:
3746
3747                         count = print_queue_status(p->msg_ctx, snum, &queue,
3748                                                    &status);
3749
3750                         for (j=0; j<count; j++) {
3751                                 construct_notify_jobs_info(p->msg_ctx,
3752                                                            &queue[j], info,
3753                                                            pinfo2, snum,
3754                                                            &option_type,
3755                                                            queue[j].job,
3756                                                            mem_ctx);
3757                         }
3758
3759                         SAFE_FREE(queue);
3760                         break;
3761                 }
3762         }
3763
3764         /*
3765          * Debugging information, don't delete.
3766          */
3767         /*
3768         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3769         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3770         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3771
3772         for (i=0; i<info->count; i++) {
3773                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3774                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3775                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3776         }
3777         */
3778
3779         talloc_free(pinfo2);
3780         return WERR_OK;
3781 }
3782
3783 /****************************************************************
3784  _spoolss_RouterRefreshPrinterChangeNotify
3785 ****************************************************************/
3786
3787 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3788                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3789 {
3790         struct spoolss_NotifyInfo *info;
3791
3792         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3793         WERROR result = WERR_BADFID;
3794
3795         /* we always have a spoolss_NotifyInfo struct */
3796         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3797         if (!info) {
3798                 result = WERR_NOMEM;
3799                 goto done;
3800         }
3801
3802         *r->out.info = info;
3803
3804         if (!Printer) {
3805                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3806                         "Invalid handle (%s:%u:%u).\n",
3807                         OUR_HANDLE(r->in.handle)));
3808                 goto done;
3809         }
3810
3811         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3812
3813         /*
3814          *      We are now using the change value, and
3815          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3816          *      I don't have a global notification system, I'm sending back all the
3817          *      information even when _NOTHING_ has changed.
3818          */
3819
3820         /* We need to keep track of the change value to send back in
3821            RRPCN replies otherwise our updates are ignored. */
3822
3823         Printer->notify.fnpcn = true;
3824
3825         if (Printer->notify.cli_chan != NULL &&
3826             Printer->notify.cli_chan->active_connections > 0) {
3827                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3828                         "Saving change value in request [%x]\n",
3829                         r->in.change_low));
3830                 Printer->notify.change = r->in.change_low;
3831         }
3832
3833         /* just ignore the spoolss_NotifyOption */
3834
3835         switch (Printer->printer_type) {
3836                 case SPLHND_SERVER:
3837                         result = printserver_notify_info(p, r->in.handle,
3838                                                          info, p->mem_ctx);
3839                         break;
3840
3841                 case SPLHND_PRINTER:
3842                         result = printer_notify_info(p, r->in.handle,
3843                                                      info, p->mem_ctx);
3844                         break;
3845         }
3846
3847         Printer->notify.fnpcn = false;
3848
3849 done:
3850         return result;
3851 }
3852
3853 /********************************************************************
3854  ********************************************************************/
3855
3856 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3857                                  const char *servername,
3858                                  const char *printername,
3859                                  const char **printername_p)
3860 {
3861         /* FIXME: add lp_force_printername() */
3862
3863         if (servername == NULL) {
3864                 *printername_p = talloc_strdup(mem_ctx, printername);
3865                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3866                 return WERR_OK;
3867         }
3868
3869         if (servername[0] == '\\' && servername[1] == '\\') {
3870                 servername += 2;
3871         }
3872
3873         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3874         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3875
3876         return WERR_OK;
3877 }
3878
3879 /********************************************************************
3880  ********************************************************************/
3881
3882 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3883                                           const char *printername)
3884 {
3885         if (dm == NULL) {
3886                 return;
3887         }
3888
3889         dm->devicename = talloc_strndup(dm, printername,
3890                                         MIN(strlen(printername), 31));
3891 }
3892
3893 /********************************************************************
3894  * construct_printer_info_0
3895  * fill a printer_info_0 struct
3896  ********************************************************************/
3897
3898 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3899                                       const struct auth_session_info *session_info,
3900                                       struct messaging_context *msg_ctx,
3901                                       struct spoolss_PrinterInfo2 *info2,
3902                                       const char *servername,
3903                                       struct spoolss_PrinterInfo0 *r,
3904                                       int snum)
3905 {
3906         int count;
3907         struct printer_session_counter *session_counter;
3908         struct timeval setuptime;
3909         print_status_struct status;
3910         WERROR result;
3911
3912         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3913         if (!W_ERROR_IS_OK(result)) {
3914                 return result;
3915         }
3916
3917         if (servername) {
3918                 r->servername = talloc_strdup(mem_ctx, servername);
3919                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3920         } else {
3921                 r->servername = NULL;
3922         }
3923
3924         count = print_queue_length(msg_ctx, snum, &status);
3925
3926         /* check if we already have a counter for this printer */
3927         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3928                 if (session_counter->snum == snum)
3929                         break;
3930         }
3931
3932         /* it's the first time, add it to the list */
3933         if (session_counter == NULL) {
3934                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3935                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3936                 session_counter->snum           = snum;
3937                 session_counter->counter        = 0;
3938                 DLIST_ADD(counter_list, session_counter);
3939         }
3940
3941         /* increment it */
3942         session_counter->counter++;
3943
3944         r->cjobs                        = count;
3945         r->total_jobs                   = 0;
3946         r->total_bytes                  = 0;
3947
3948         get_startup_time(&setuptime);
3949         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3950
3951         /* JFM:
3952          * the global_counter should be stored in a TDB as it's common to all the clients
3953          * and should be zeroed on samba startup
3954          */
3955         r->global_counter               = session_counter->counter;
3956         r->total_pages                  = 0;
3957         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3958         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3959         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3960         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3961         r->spooling                     = 0;
3962         r->max_spooling                 = 0;
3963         r->session_counter              = session_counter->counter;
3964         r->num_error_out_of_paper       = 0x0;
3965         r->num_error_not_ready          = 0x0;          /* number of print failure */
3966         r->job_error                    = 0x0;
3967         r->number_of_processors         = 0x1;
3968         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3969         r->high_part_total_bytes        = 0x0;
3970
3971         /* ChangeID in milliseconds*/
3972         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3973                                     info2->sharename, &r->change_id);
3974
3975         r->last_error                   = WERR_OK;
3976         r->status                       = nt_printq_status(status.status);
3977         r->enumerate_network_printers   = 0x0;
3978         r->c_setprinter                 = 0x0;
3979         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3980         r->processor_level              = 0x6;          /* 6  ???*/
3981         r->ref_ic                       = 0;
3982         r->reserved2                    = 0;
3983         r->reserved3                    = 0;
3984
3985         return WERR_OK;
3986 }
3987
3988
3989 /********************************************************************
3990  * construct_printer_info1
3991  * fill a spoolss_PrinterInfo1 struct
3992 ********************************************************************/
3993
3994 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3995                                       const struct spoolss_PrinterInfo2 *info2,
3996                                       uint32_t flags,
3997                                       const char *servername,
3998                                       struct spoolss_PrinterInfo1 *r,
3999                                       int snum)
4000 {
4001         WERROR result;
4002
4003         r->flags                = flags;
4004
4005         if (info2->comment == NULL || info2->comment[0] == '\0') {
4006                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4007         } else {
4008                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4009         }
4010         W_ERROR_HAVE_NO_MEMORY(r->comment);
4011
4012         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4013         if (!W_ERROR_IS_OK(result)) {
4014                 return result;
4015         }
4016
4017         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
4018                                                   r->name,
4019                                                   info2->drivername,
4020                                                   r->comment);
4021         W_ERROR_HAVE_NO_MEMORY(r->description);
4022
4023         return WERR_OK;
4024 }
4025
4026 /********************************************************************
4027  * construct_printer_info2
4028  * fill a spoolss_PrinterInfo2 struct
4029 ********************************************************************/
4030
4031 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4032                                       struct messaging_context *msg_ctx,
4033                                       const struct spoolss_PrinterInfo2 *info2,
4034                                       const char *servername,
4035                                       struct spoolss_PrinterInfo2 *r,
4036                                       int snum)
4037 {
4038         int count;
4039         print_status_struct status;
4040         WERROR result;
4041
4042         count = print_queue_length(msg_ctx, snum, &status);
4043
4044         if (servername) {
4045                 r->servername           = talloc_strdup(mem_ctx, servername);
4046                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4047         } else {
4048                 r->servername           = NULL;
4049         }
4050
4051         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4052         if (!W_ERROR_IS_OK(result)) {
4053                 return result;
4054         }
4055
4056         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4057         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4058         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4059         W_ERROR_HAVE_NO_MEMORY(r->portname);
4060         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4061         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4062
4063         if (info2->comment[0] == '\0') {
4064                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4065         } else {
4066                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4067         }
4068         W_ERROR_HAVE_NO_MEMORY(r->comment);
4069
4070         r->location     = talloc_strdup(mem_ctx, info2->location);
4071         if (info2->location[0] == '\0') {
4072                 const char *loc = NULL;
4073                 NTSTATUS nt_status;
4074
4075                 nt_status = printer_list_get_printer(mem_ctx,
4076                                                      info2->sharename,
4077                                                      NULL,
4078                                                      &loc,
4079                                                      NULL);
4080                 if (NT_STATUS_IS_OK(nt_status)) {
4081                         if (loc != NULL) {
4082                                 r->location = talloc_strdup(mem_ctx, loc);
4083                         }
4084                 }
4085         }
4086         W_ERROR_HAVE_NO_MEMORY(r->location);
4087
4088         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4089         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4090         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4091         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4092         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4093         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4094         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4095         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4096
4097         r->attributes           = info2->attributes;
4098
4099         r->priority             = info2->priority;
4100         r->defaultpriority      = info2->defaultpriority;
4101         r->starttime            = info2->starttime;
4102         r->untiltime            = info2->untiltime;
4103         r->status               = nt_printq_status(status.status);
4104         r->cjobs                = count;
4105         r->averageppm           = info2->averageppm;
4106
4107         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4108         if (!r->devmode) {
4109                 DEBUG(8,("Returning NULL Devicemode!\n"));
4110         }
4111
4112         compose_devicemode_devicename(r->devmode, r->printername);
4113
4114         r->secdesc = NULL;
4115
4116         if (info2->secdesc != NULL) {
4117                 /* don't use talloc_steal() here unless you do a deep steal of all
4118                    the SEC_DESC members */
4119
4120                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4121         }
4122
4123         return WERR_OK;
4124 }
4125
4126 /********************************************************************
4127  * construct_printer_info3
4128  * fill a spoolss_PrinterInfo3 struct
4129  ********************************************************************/
4130
4131 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4132                                       const struct spoolss_PrinterInfo2 *info2,
4133                                       const char *servername,
4134                                       struct spoolss_PrinterInfo3 *r,
4135                                       int snum)
4136 {
4137         /* These are the components of the SD we are returning. */
4138
4139         if (info2->secdesc != NULL) {
4140                 /* don't use talloc_steal() here unless you do a deep steal of all
4141                    the SEC_DESC members */
4142
4143                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4144                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4145         }
4146
4147         return WERR_OK;
4148 }
4149
4150 /********************************************************************
4151  * construct_printer_info4
4152  * fill a spoolss_PrinterInfo4 struct
4153  ********************************************************************/
4154
4155 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4156                                       const struct spoolss_PrinterInfo2 *info2,
4157                                       const char *servername,
4158                                       struct spoolss_PrinterInfo4 *r,
4159                                       int snum)
4160 {
4161         WERROR result;
4162
4163         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4164         if (!W_ERROR_IS_OK(result)) {
4165                 return result;
4166         }
4167
4168         if (servername) {
4169                 r->servername   = talloc_strdup(mem_ctx, servername);
4170                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4171         } else {
4172                 r->servername = NULL;
4173         }
4174
4175         r->attributes   = info2->attributes;
4176
4177         return WERR_OK;
4178 }
4179
4180 /********************************************************************
4181  * construct_printer_info5
4182  * fill a spoolss_PrinterInfo5 struct
4183  ********************************************************************/
4184
4185 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4186                                       const struct spoolss_PrinterInfo2 *info2,
4187                                       const char *servername,
4188                                       struct spoolss_PrinterInfo5 *r,
4189                                       int snum)
4190 {
4191         WERROR result;
4192
4193         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4194         if (!W_ERROR_IS_OK(result)) {
4195                 return result;
4196         }
4197
4198         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4199         W_ERROR_HAVE_NO_MEMORY(r->portname);
4200
4201         r->attributes   = info2->attributes;
4202
4203         /* these two are not used by NT+ according to MSDN */
4204         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4205         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4206
4207         return WERR_OK;
4208 }
4209
4210 /********************************************************************
4211  * construct_printer_info_6
4212  * fill a spoolss_PrinterInfo6 struct
4213  ********************************************************************/
4214
4215 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4216                                       struct messaging_context *msg_ctx,
4217                                       const struct spoolss_PrinterInfo2 *info2,
4218                                       const char *servername,
4219                                       struct spoolss_PrinterInfo6 *r,
4220                                       int snum)
4221 {
4222         print_status_struct status;
4223
4224         print_queue_length(msg_ctx, snum, &status);
4225
4226         r->status = nt_printq_status(status.status);
4227
4228         return WERR_OK;
4229 }
4230
4231 /********************************************************************
4232  * construct_printer_info7
4233  * fill a spoolss_PrinterInfo7 struct
4234  ********************************************************************/
4235
4236 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4237                                       struct messaging_context *msg_ctx,
4238                                       const char *servername,
4239                                       struct spoolss_PrinterInfo7 *r,
4240                                       int snum)
4241 {
4242         const struct auth_session_info *session_info = get_session_info_system();
4243         struct GUID guid;
4244
4245         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4246                                  servername,
4247                                  lp_servicename(snum), &guid, NULL)) {
4248                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4249                 r->action = DSPRINT_PUBLISH;
4250         } else {
4251                 r->guid = talloc_strdup(mem_ctx, "");
4252                 r->action = DSPRINT_UNPUBLISH;
4253         }
4254         W_ERROR_HAVE_NO_MEMORY(r->guid);
4255
4256         return WERR_OK;
4257 }
4258
4259 /********************************************************************
4260  * construct_printer_info8
4261  * fill a spoolss_PrinterInfo8 struct
4262  ********************************************************************/
4263
4264 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4265                                       const struct spoolss_PrinterInfo2 *info2,
4266                                       const char *servername,
4267                                       struct spoolss_DeviceModeInfo *r,
4268                                       int snum)
4269 {
4270         WERROR result;
4271         const char *printername;
4272
4273         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4274         if (!W_ERROR_IS_OK(result)) {
4275                 return result;
4276         }
4277
4278         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4279         if (!r->devmode) {
4280                 DEBUG(8,("Returning NULL Devicemode!\n"));
4281         }
4282
4283         compose_devicemode_devicename(r->devmode, printername);
4284
4285         return WERR_OK;
4286 }
4287
4288
4289 /********************************************************************
4290 ********************************************************************/
4291
4292 static bool snum_is_shared_printer(int snum)
4293 {
4294         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4295 }
4296
4297 /********************************************************************
4298  Spoolss_enumprinters.
4299 ********************************************************************/
4300
4301 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4302                                            const struct auth_session_info *session_info,
4303                                            struct messaging_context *msg_ctx,
4304                                            const char *servername,
4305                                            uint32_t level,
4306                                            uint32_t flags,
4307                                            union spoolss_PrinterInfo **info_p,
4308                                            uint32_t *count_p)
4309 {
4310         int snum;
4311         int n_services = lp_numservices();
4312         union spoolss_PrinterInfo *info = NULL;
4313         uint32_t count = 0;
4314         WERROR result = WERR_OK;
4315         struct dcerpc_binding_handle *b = NULL;
4316         TALLOC_CTX *tmp_ctx = NULL;
4317
4318         tmp_ctx = talloc_new(mem_ctx);
4319         if (!tmp_ctx) {
4320                 return WERR_NOMEM;
4321         }
4322
4323         *count_p = 0;
4324         *info_p = NULL;
4325
4326         for (snum = 0; snum < n_services; snum++) {
4327
4328                 const char *printer;
4329                 struct spoolss_PrinterInfo2 *info2;
4330
4331                 if (!snum_is_shared_printer(snum)) {
4332                         continue;
4333                 }
4334
4335                 printer = lp_const_servicename(snum);
4336
4337                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4338                         printer, snum));
4339
4340                 if (b == NULL) {
4341                         result = winreg_printer_binding_handle(tmp_ctx,
4342                                                                session_info,
4343                                                                msg_ctx,
4344                                                                &b);
4345                         if (!W_ERROR_IS_OK(result)) {
4346                                 goto out;
4347                         }
4348                 }
4349
4350                 result = winreg_create_printer(tmp_ctx, b,
4351                                                printer);
4352                 if (!W_ERROR_IS_OK(result)) {
4353                         goto out;
4354                 }
4355
4356                 info = talloc_realloc(tmp_ctx, info,
4357                                             union spoolss_PrinterInfo,
4358                                             count + 1);
4359                 if (!info) {
4360                         result = WERR_NOMEM;
4361                         goto out;
4362                 }
4363
4364                 result = winreg_get_printer(tmp_ctx, b,
4365                                             printer, &info2);
4366                 if (!W_ERROR_IS_OK(result)) {
4367                         goto out;
4368                 }
4369
4370                 switch (level) {
4371                 case 0:
4372                         result = construct_printer_info0(info, session_info,
4373                                                          msg_ctx, info2,
4374                                                          servername,
4375                                                          &info[count].info0, snum);
4376                         break;
4377                 case 1:
4378                         result = construct_printer_info1(info, info2, flags,
4379                                                          servername,
4380                                                          &info[count].info1, snum);
4381                         break;
4382                 case 2:
4383                         result = construct_printer_info2(info, msg_ctx, info2,
4384                                                          servername,
4385                                                          &info[count].info2, snum);
4386                         break;
4387                 case 4:
4388                         result = construct_printer_info4(info, info2,
4389                                                          servername,
4390                                                          &info[count].info4, snum);
4391                         break;
4392                 case 5:
4393                         result = construct_printer_info5(info, info2,
4394                                                          servername,
4395                                                          &info[count].info5, snum);
4396                         break;
4397
4398                 default:
4399                         result = WERR_UNKNOWN_LEVEL;
4400                         goto out;
4401                 }
4402
4403                 if (!W_ERROR_IS_OK(result)) {
4404                         goto out;
4405                 }
4406
4407                 count++;
4408         }
4409
4410 out:
4411         if (W_ERROR_IS_OK(result)) {
4412                 *info_p = talloc_move(mem_ctx, &info);
4413                 *count_p = count;
4414         }
4415
4416         talloc_free(tmp_ctx);
4417
4418         return result;
4419 }
4420
4421 /********************************************************************
4422  * handle enumeration of printers at level 0
4423  ********************************************************************/
4424
4425 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4426                                   const struct auth_session_info *session_info,
4427                                   struct messaging_context *msg_ctx,
4428                                   uint32_t flags,
4429                                   const char *servername,
4430                                   union spoolss_PrinterInfo **info,
4431                                   uint32_t *count)
4432 {
4433         DEBUG(4,("enum_all_printers_info_0\n"));
4434
4435         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4436                                             servername, 0, flags, info, count);
4437 }
4438
4439
4440 /********************************************************************
4441 ********************************************************************/
4442
4443 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4444                                        const struct auth_session_info *session_info,
4445                                        struct messaging_context *msg_ctx,
4446                                        const char *servername,
4447                                        uint32_t flags,
4448                                        union spoolss_PrinterInfo **info,
4449                                        uint32_t *count)
4450 {
4451         DEBUG(4,("enum_all_printers_info_1\n"));
4452
4453         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4454                                             servername, 1, flags, info, count);
4455 }
4456
4457 /********************************************************************
4458  enum_all_printers_info_1_local.
4459 *********************************************************************/
4460
4461 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4462                                              const struct auth_session_info *session_info,
4463                                              struct messaging_context *msg_ctx,
4464                                              const char *servername,
4465                                              union spoolss_PrinterInfo **info,
4466                                              uint32_t *count)
4467 {
4468         DEBUG(4,("enum_all_printers_info_1_local\n"));
4469
4470         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4471                                         servername, PRINTER_ENUM_ICON8, info, count);
4472 }
4473
4474 /********************************************************************
4475  enum_all_printers_info_1_name.
4476 *********************************************************************/
4477
4478 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4479                                             const struct auth_session_info *session_info,
4480                                             struct messaging_context *msg_ctx,
4481                                             const char *servername,
4482                                             union spoolss_PrinterInfo **info,
4483                                             uint32_t *count)
4484 {
4485         const char *s = servername;
4486
4487         DEBUG(4,("enum_all_printers_info_1_name\n"));
4488
4489         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4490                 s = servername + 2;
4491         }
4492
4493         if (!is_myname_or_ipaddr(s)) {
4494                 return WERR_INVALID_NAME;
4495         }
4496
4497         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4498                                         servername, PRINTER_ENUM_ICON8, info, count);
4499 }
4500
4501 /********************************************************************
4502  enum_all_printers_info_1_network.
4503 *********************************************************************/
4504
4505 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4506                                                const struct auth_session_info *session_info,
4507                                                struct messaging_context *msg_ctx,
4508                                                const char *servername,
4509                                                union spoolss_PrinterInfo **info,
4510                                                uint32_t *count)
4511 {
4512         const char *s = servername;
4513
4514         DEBUG(4,("enum_all_printers_info_1_network\n"));
4515
4516         /* If we respond to a enum_printers level 1 on our name with flags
4517            set to PRINTER_ENUM_REMOTE with a list of printers then these
4518            printers incorrectly appear in the APW browse list.
4519            Specifically the printers for the server appear at the workgroup
4520            level where all the other servers in the domain are
4521            listed. Windows responds to this call with a
4522            WERR_CAN_NOT_COMPLETE so we should do the same. */
4523
4524         if (servername[0] == '\\' && servername[1] == '\\') {
4525                  s = servername + 2;
4526         }
4527
4528         if (is_myname_or_ipaddr(s)) {
4529                  return WERR_CAN_NOT_COMPLETE;
4530         }
4531
4532         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4533                                         servername, PRINTER_ENUM_NAME, info, count);
4534 }
4535
4536 /********************************************************************
4537  * api_spoolss_enumprinters
4538  *
4539  * called from api_spoolss_enumprinters (see this to understand)
4540  ********************************************************************/
4541
4542 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4543                                        const struct auth_session_info *session_info,
4544                                        struct messaging_context *msg_ctx,
4545                                        const char *servername,
4546                                        union spoolss_PrinterInfo **info,
4547                                        uint32_t *count)
4548 {
4549         DEBUG(4,("enum_all_printers_info_2\n"));
4550
4551         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4552                                             servername, 2, 0, info, count);
4553 }
4554
4555 /********************************************************************
4556  * handle enumeration of printers at level 1
4557  ********************************************************************/
4558
4559 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4560                                   const struct auth_session_info *session_info,
4561                                   struct messaging_context *msg_ctx,
4562                                   uint32_t flags,
4563                                   const char *servername,
4564                                   union spoolss_PrinterInfo **info,
4565                                   uint32_t *count)
4566 {
4567         /* Not all the flags are equals */
4568
4569         if (flags & PRINTER_ENUM_LOCAL) {
4570                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4571                                                       msg_ctx, servername, info, count);
4572         }
4573
4574         if (flags & PRINTER_ENUM_NAME) {
4575                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4576                                                      msg_ctx, servername, info,
4577                                                      count);
4578         }
4579
4580         if (flags & PRINTER_ENUM_NETWORK) {
4581                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4582                                                         msg_ctx, servername, info,
4583                                                         count);
4584         }
4585
4586         return WERR_OK; /* NT4sp5 does that */
4587 }
4588
4589 /********************************************************************
4590  * handle enumeration of printers at level 2
4591  ********************************************************************/
4592
4593 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4594                                   const struct auth_session_info *session_info,
4595                                   struct messaging_context *msg_ctx,
4596                                   uint32_t flags,
4597                                   const char *servername,
4598                                   union spoolss_PrinterInfo **info,
4599                                   uint32_t *count)
4600 {
4601         if (flags & PRINTER_ENUM_LOCAL) {
4602
4603                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4604                                                 servername,
4605                                                 info, count);
4606         }
4607
4608         if (flags & PRINTER_ENUM_NAME) {
4609                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4610                         return WERR_INVALID_NAME;
4611                 }
4612
4613                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4614                                                 servername,
4615                                                 info, count);
4616         }
4617
4618         if (flags & PRINTER_ENUM_REMOTE) {
4619                 return WERR_UNKNOWN_LEVEL;
4620         }
4621
4622         return WERR_OK;
4623 }
4624
4625 /********************************************************************
4626  * handle enumeration of printers at level 4
4627  ********************************************************************/
4628
4629 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4630                                   const struct auth_session_info *session_info,
4631                                   struct messaging_context *msg_ctx,
4632                                   uint32_t flags,
4633                                   const char *servername,
4634                                   union spoolss_PrinterInfo **info,
4635                                   uint32_t *count)
4636 {
4637         DEBUG(4,("enum_all_printers_info_4\n"));
4638
4639         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4640                                             servername, 4, flags, info, count);
4641 }
4642
4643
4644 /********************************************************************
4645  * handle enumeration of printers at level 5
4646  ********************************************************************/
4647
4648 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4649                                   const struct auth_session_info *session_info,
4650                                   struct messaging_context *msg_ctx,
4651                                   uint32_t flags,
4652                                   const char *servername,
4653                                   union spoolss_PrinterInfo **info,
4654                                   uint32_t *count)
4655 {
4656         DEBUG(4,("enum_all_printers_info_5\n"));
4657
4658         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4659                                             servername, 5, flags, info, count);
4660 }
4661
4662 /****************************************************************
4663  _spoolss_EnumPrinters
4664 ****************************************************************/
4665
4666 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4667                              struct spoolss_EnumPrinters *r)
4668 {
4669         const struct auth_session_info *session_info = get_session_info_system();
4670         WERROR result;
4671
4672         /* that's an [in out] buffer */
4673
4674         if (!r->in.buffer && (r->in.offered != 0)) {
4675                 return WERR_INVALID_PARAM;
4676         }
4677
4678         DEBUG(4,("_spoolss_EnumPrinters\n"));
4679
4680         *r->out.needed = 0;
4681         *r->out.count = 0;
4682         *r->out.info = NULL;
4683
4684         /*
4685          * Level 1:
4686          *          flags==PRINTER_ENUM_NAME
4687          *           if name=="" then enumerates all printers
4688          *           if name!="" then enumerate the printer
4689          *          flags==PRINTER_ENUM_REMOTE
4690          *          name is NULL, enumerate printers
4691          * Level 2: name!="" enumerates printers, name can't be NULL
4692          * Level 3: doesn't exist
4693          * Level 4: does a local registry lookup
4694          * Level 5: same as Level 2
4695          */
4696
4697         if (r->in.server && r->in.server[0] == '\0') {
4698                 r->in.server = NULL;
4699         }
4700
4701         switch (r->in.level) {
4702         case 0:
4703                 result = enumprinters_level0(p->mem_ctx, session_info,
4704                                              p->msg_ctx, r->in.flags,
4705                                              r->in.server,
4706                                              r->out.info, r->out.count);
4707                 break;
4708         case 1:
4709                 result = enumprinters_level1(p->mem_ctx, session_info,
4710                                              p->msg_ctx, r->in.flags,
4711                                              r->in.server,
4712                                              r->out.info, r->out.count);
4713                 break;
4714         case 2:
4715                 result = enumprinters_level2(p->mem_ctx, session_info,
4716                                              p->msg_ctx, r->in.flags,
4717                                              r->in.server,
4718                                              r->out.info, r->out.count);
4719                 break;
4720         case 4:
4721                 result = enumprinters_level4(p->mem_ctx, session_info,
4722                                              p->msg_ctx, r->in.flags,
4723                                              r->in.server,
4724                                              r->out.info, r->out.count);
4725                 break;
4726         case 5:
4727                 result = enumprinters_level5(p->mem_ctx, session_info,
4728                                              p->msg_ctx, r->in.flags,
4729                                              r->in.server,
4730                                              r->out.info, r->out.count);
4731                 break;
4732         default:
4733                 return WERR_UNKNOWN_LEVEL;
4734         }
4735
4736         if (!W_ERROR_IS_OK(result)) {
4737                 return result;
4738         }
4739
4740         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4741                                                      spoolss_EnumPrinters,
4742                                                      *r->out.info, r->in.level,
4743                                                      *r->out.count);
4744         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4745         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4746
4747         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4748 }
4749
4750 /****************************************************************
4751  _spoolss_GetPrinter
4752 ****************************************************************/
4753
4754 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4755                            struct spoolss_GetPrinter *r)
4756 {
4757         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4758         struct spoolss_PrinterInfo2 *info2 = NULL;
4759         WERROR result = WERR_OK;
4760         int snum;
4761
4762         /* that's an [in out] buffer */
4763
4764         if (!r->in.buffer && (r->in.offered != 0)) {
4765                 return WERR_INVALID_PARAM;
4766         }
4767
4768         *r->out.needed = 0;
4769
4770         if (Printer == NULL) {
4771                 return WERR_BADFID;
4772         }
4773
4774         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4775                 return WERR_BADFID;
4776         }
4777
4778         result = winreg_get_printer_internal(p->mem_ctx,
4779                                     get_session_info_system(),
4780                                     p->msg_ctx,
4781                                     lp_const_servicename(snum),
4782                                     &info2);
4783         if (!W_ERROR_IS_OK(result)) {
4784                 goto out;
4785         }
4786
4787         switch (r->in.level) {
4788         case 0:
4789                 result = construct_printer_info0(p->mem_ctx,
4790                                                  get_session_info_system(),
4791                                                  p->msg_ctx,
4792                                                  info2,
4793                                                  Printer->servername,
4794                                                  &r->out.info->info0,
4795                                                  snum);
4796                 break;
4797         case 1:
4798                 result = construct_printer_info1(p->mem_ctx, info2,
4799                                                  PRINTER_ENUM_ICON8,
4800                                                  Printer->servername,
4801                                                  &r->out.info->info1, snum);
4802                 break;
4803         case 2:
4804                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4805                                                  Printer->servername,
4806                                                  &r->out.info->info2, snum);
4807                 break;
4808         case 3:
4809                 result = construct_printer_info3(p->mem_ctx, info2,
4810                                                  Printer->servername,
4811                                                  &r->out.info->info3, snum);
4812                 break;
4813         case 4:
4814                 result = construct_printer_info4(p->mem_ctx, info2,
4815                                                  Printer->servername,
4816                                                  &r->out.info->info4, snum);
4817                 break;
4818         case 5:
4819                 result = construct_printer_info5(p->mem_ctx, info2,
4820                                                  Printer->servername,
4821                                                  &r->out.info->info5, snum);
4822                 break;
4823         case 6:
4824                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4825                                                  Printer->servername,
4826                                                  &r->out.info->info6, snum);
4827                 break;
4828         case 7:
4829                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4830                                                  Printer->servername,
4831                                                  &r->out.info->info7, snum);
4832                 break;
4833         case 8:
4834                 result = construct_printer_info8(p->mem_ctx, info2,
4835                                                  Printer->servername,
4836                                                  &r->out.info->info8, snum);
4837                 break;
4838         default:
4839                 result = WERR_UNKNOWN_LEVEL;
4840                 break;
4841         }
4842         TALLOC_FREE(info2);
4843
4844  out:
4845         if (!W_ERROR_IS_OK(result)) {
4846                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4847                           r->in.level, win_errstr(result)));
4848                 TALLOC_FREE(r->out.info);
4849                 return result;
4850         }
4851
4852         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4853                                                r->out.info, r->in.level);
4854         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4855
4856         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4857 }
4858
4859 /********************************************************************
4860  ********************************************************************/
4861
4862 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4863         do { \
4864                 if (in && strlen(in)) { \
4865                         out = talloc_strdup(mem_ctx, in); \
4866                 } else { \
4867                         out = talloc_strdup(mem_ctx, ""); \
4868                 } \
4869                 W_ERROR_HAVE_NO_MEMORY(out); \
4870         } while (0);
4871
4872 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4873         do { \
4874                 if (in && strlen(in)) { \
4875                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4876                 } else { \
4877                         out = talloc_strdup(mem_ctx, ""); \
4878                 } \
4879                 W_ERROR_HAVE_NO_MEMORY(out); \
4880         } while (0);
4881
4882 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4883                                                   const char **string_array,
4884                                                   const char ***presult,
4885                                                   const char *cservername,
4886                                                   const char *arch,
4887                                                   int version)
4888 {
4889         int i, num_strings = 0;
4890         const char **array = NULL;
4891
4892         if (string_array == NULL) {
4893                 return WERR_INVALID_PARAMETER;
4894         }
4895
4896         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4897                 const char *str = NULL;
4898
4899                 if (cservername == NULL || arch == NULL) {
4900                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4901                 } else {
4902                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4903                 }
4904
4905                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4906                         TALLOC_FREE(array);
4907                         return WERR_NOMEM;
4908                 }
4909         }
4910
4911         if (i > 0) {
4912                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4913                              &array, &num_strings);
4914         }
4915
4916         if (presult) {
4917                 *presult = array;
4918         }
4919
4920         return WERR_OK;
4921 }
4922
4923 /********************************************************************
4924  * fill a spoolss_DriverInfo1 struct
4925  ********************************************************************/
4926
4927 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4928                                         struct spoolss_DriverInfo1 *r,
4929                                         const struct spoolss_DriverInfo8 *driver,
4930                                         const char *servername)
4931 {
4932         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4933         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4934
4935         return WERR_OK;
4936 }
4937
4938 /********************************************************************
4939  * fill a spoolss_DriverInfo2 struct
4940  ********************************************************************/
4941
4942 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4943                                         struct spoolss_DriverInfo2 *r,
4944                                         const struct spoolss_DriverInfo8 *driver,
4945                                         const char *servername)
4946
4947 {
4948         const char *cservername = canon_servername(servername);
4949
4950         r->version              = driver->version;
4951
4952         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4953         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4954         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4955         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4956
4957         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4958                                driver->architecture,
4959                                driver->version,
4960                                driver->driver_path,
4961                                r->driver_path);
4962
4963         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4964                                driver->architecture,
4965                                driver->version,
4966                                driver->data_file,
4967                                r->data_file);
4968
4969         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4970                                driver->architecture,
4971                                driver->version,
4972                                driver->config_file,
4973                                r->config_file);
4974
4975         return WERR_OK;
4976 }
4977
4978 /********************************************************************
4979  * fill a spoolss_DriverInfo3 struct
4980  ********************************************************************/
4981
4982 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4983                                         struct spoolss_DriverInfo3 *r,
4984                                         const struct spoolss_DriverInfo8 *driver,
4985                                         const char *servername)
4986 {
4987         const char *cservername = canon_servername(servername);
4988
4989         r->version              = driver->version;
4990
4991         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4992         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4993         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4994         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4995
4996         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4997                                driver->architecture,
4998                                driver->version,
4999                                driver->driver_path,
5000                                r->driver_path);
5001
5002         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5003                                driver->architecture,
5004                                driver->version,
5005                                driver->data_file,
5006                                r->data_file);
5007
5008         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5009                                driver->architecture,
5010                                driver->version,
5011                                driver->config_file,
5012                                r->config_file);
5013
5014         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5015                                driver->architecture,
5016                                driver->version,
5017                                driver->help_file,
5018                                r->help_file);
5019
5020         FILL_DRIVER_STRING(mem_ctx,
5021                            driver->monitor_name,
5022                            r->monitor_name);
5023
5024         FILL_DRIVER_STRING(mem_ctx,
5025                            driver->default_datatype,
5026                            r->default_datatype);
5027
5028         return string_array_from_driver_info(mem_ctx,
5029                                              driver->dependent_files,
5030                                              &r->dependent_files,
5031                                              cservername,
5032                                              driver->architecture,
5033                                              driver->version);
5034 }
5035
5036 /********************************************************************
5037  * fill a spoolss_DriverInfo4 struct
5038  ********************************************************************/
5039
5040 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5041                                         struct spoolss_DriverInfo4 *r,
5042                                         const struct spoolss_DriverInfo8 *driver,
5043                                         const char *servername)
5044 {
5045         const char *cservername = canon_servername(servername);
5046         WERROR result;
5047
5048         r->version              = driver->version;
5049
5050         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5051         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5052         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5053         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5054
5055         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5056                                driver->architecture,
5057                                driver->version,
5058                                driver->driver_path,
5059                                r->driver_path);
5060
5061         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5062                                driver->architecture,
5063                                driver->version,
5064                                driver->data_file,
5065                                r->data_file);
5066
5067         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5068                                driver->architecture,
5069                                driver->version,
5070                                driver->config_file,
5071                                r->config_file);
5072
5073         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5074                                driver->architecture,
5075                                driver->version,
5076                                driver->help_file,
5077                                r->help_file);
5078
5079         result = string_array_from_driver_info(mem_ctx,
5080                                                driver->dependent_files,
5081                                                &r->dependent_files,
5082                                                cservername,
5083                                                driver->architecture,
5084                                                driver->version);
5085         if (!W_ERROR_IS_OK(result)) {
5086                 return result;
5087         }
5088
5089         FILL_DRIVER_STRING(mem_ctx,
5090                            driver->monitor_name,
5091                            r->monitor_name);
5092
5093         FILL_DRIVER_STRING(mem_ctx,
5094                            driver->default_datatype,
5095                            r->default_datatype);
5096
5097
5098         result = string_array_from_driver_info(mem_ctx,
5099                                                driver->previous_names,
5100                                                &r->previous_names,
5101                                                NULL, NULL, 0);
5102
5103         return result;
5104 }
5105
5106 /********************************************************************
5107  * fill a spoolss_DriverInfo5 struct
5108  ********************************************************************/
5109
5110 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5111                                         struct spoolss_DriverInfo5 *r,
5112                                         const struct spoolss_DriverInfo8 *driver,
5113                                         const char *servername)
5114 {
5115         const char *cservername = canon_servername(servername);
5116
5117         r->version              = driver->version;
5118
5119         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5120         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5121         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5122         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5123
5124         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5125                                driver->architecture,
5126                                driver->version,
5127                                driver->driver_path,
5128                                r->driver_path);
5129
5130         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5131                                driver->architecture,
5132                                driver->version,
5133                                driver->data_file,
5134                                r->data_file);
5135
5136         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5137                                driver->architecture,
5138                                driver->version,
5139                                driver->config_file,
5140                                r->config_file);
5141
5142         r->driver_attributes    = 0;
5143         r->config_version       = 0;
5144         r->driver_version       = 0;
5145
5146         return WERR_OK;
5147 }
5148 /********************************************************************
5149  * fill a spoolss_DriverInfo6 struct
5150  ********************************************************************/
5151
5152 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5153                                         struct spoolss_DriverInfo6 *r,
5154                                         const struct spoolss_DriverInfo8 *driver,
5155                                         const char *servername)
5156 {
5157         const char *cservername = canon_servername(servername);
5158         WERROR result;
5159
5160         r->version              = driver->version;
5161
5162         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5163         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5164         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5165         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5166
5167         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5168                                driver->architecture,
5169                                driver->version,
5170                                driver->driver_path,
5171                                r->driver_path);
5172
5173         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5174                                driver->architecture,
5175                                driver->version,
5176                                driver->data_file,
5177                                r->data_file);
5178
5179         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5180                                driver->architecture,
5181                                driver->version,
5182                                driver->config_file,
5183                                r->config_file);
5184
5185         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5186                                driver->architecture,
5187                                driver->version,
5188                                driver->help_file,
5189                                r->help_file);
5190
5191         FILL_DRIVER_STRING(mem_ctx,
5192                            driver->monitor_name,
5193                            r->monitor_name);
5194
5195         FILL_DRIVER_STRING(mem_ctx,
5196                            driver->default_datatype,
5197                            r->default_datatype);
5198
5199         result = string_array_from_driver_info(mem_ctx,
5200                                                driver->dependent_files,
5201                                                &r->dependent_files,
5202                                                cservername,
5203                                                driver->architecture,
5204                                                driver->version);
5205         if (!W_ERROR_IS_OK(result)) {
5206                 return result;
5207         }
5208
5209         result = string_array_from_driver_info(mem_ctx,
5210                                                driver->previous_names,
5211                                                &r->previous_names,
5212                                                NULL, NULL, 0);
5213         if (!W_ERROR_IS_OK(result)) {
5214                 return result;
5215         }
5216
5217         r->driver_date          = driver->driver_date;
5218         r->driver_version       = driver->driver_version;
5219
5220         FILL_DRIVER_STRING(mem_ctx,
5221                            driver->manufacturer_name,
5222                            r->manufacturer_name);
5223         FILL_DRIVER_STRING(mem_ctx,
5224                            driver->manufacturer_url,
5225                            r->manufacturer_url);
5226         FILL_DRIVER_STRING(mem_ctx,
5227                            driver->hardware_id,
5228                            r->hardware_id);
5229         FILL_DRIVER_STRING(mem_ctx,
5230                            driver->provider,
5231                            r->provider);
5232
5233         return WERR_OK;
5234 }
5235
5236 /********************************************************************
5237  * fill a spoolss_DriverInfo8 struct
5238  ********************************************************************/
5239
5240 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5241                                         struct spoolss_DriverInfo8 *r,
5242                                         const struct spoolss_DriverInfo8 *driver,
5243                                         const char *servername)
5244 {
5245         const char *cservername = canon_servername(servername);
5246         WERROR result;
5247
5248         r->version              = driver->version;
5249
5250         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5251         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5252         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5253         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5254
5255         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5256                                driver->architecture,
5257                                driver->version,
5258                                driver->driver_path,
5259                                r->driver_path);
5260
5261         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5262                                driver->architecture,
5263                                driver->version,
5264                                driver->data_file,
5265                                r->data_file);
5266
5267         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5268                                driver->architecture,
5269                                driver->version,
5270                                driver->config_file,
5271                                r->config_file);
5272
5273         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5274                                driver->architecture,
5275                                driver->version,
5276                                driver->help_file,
5277                                r->help_file);
5278
5279         FILL_DRIVER_STRING(mem_ctx,
5280                            driver->monitor_name,
5281                            r->monitor_name);
5282
5283         FILL_DRIVER_STRING(mem_ctx,
5284                            driver->default_datatype,
5285                            r->default_datatype);
5286
5287         result = string_array_from_driver_info(mem_ctx,
5288                                                driver->dependent_files,
5289                                                &r->dependent_files,
5290                                                cservername,
5291                                                driver->architecture,
5292                                                driver->version);
5293         if (!W_ERROR_IS_OK(result)) {
5294                 return result;
5295         }
5296
5297         result = string_array_from_driver_info(mem_ctx,
5298                                                driver->previous_names,
5299                                                &r->previous_names,
5300                                                NULL, NULL, 0);
5301         if (!W_ERROR_IS_OK(result)) {
5302                 return result;
5303         }
5304
5305         r->driver_date          = driver->driver_date;
5306         r->driver_version       = driver->driver_version;
5307
5308         FILL_DRIVER_STRING(mem_ctx,
5309                            driver->manufacturer_name,
5310                            r->manufacturer_name);
5311         FILL_DRIVER_STRING(mem_ctx,
5312                            driver->manufacturer_url,
5313                            r->manufacturer_url);
5314         FILL_DRIVER_STRING(mem_ctx,
5315                            driver->hardware_id,
5316                            r->hardware_id);
5317         FILL_DRIVER_STRING(mem_ctx,
5318                            driver->provider,
5319                            r->provider);
5320
5321         FILL_DRIVER_STRING(mem_ctx,
5322                            driver->print_processor,
5323                            r->print_processor);
5324         FILL_DRIVER_STRING(mem_ctx,
5325                            driver->vendor_setup,
5326                            r->vendor_setup);
5327
5328         result = string_array_from_driver_info(mem_ctx,
5329                                                driver->color_profiles,
5330                                                &r->color_profiles,
5331                                                NULL, NULL, 0);
5332         if (!W_ERROR_IS_OK(result)) {
5333                 return result;
5334         }
5335
5336         FILL_DRIVER_STRING(mem_ctx,
5337                            driver->inf_path,
5338                            r->inf_path);
5339
5340         r->printer_driver_attributes    = driver->printer_driver_attributes;
5341
5342         result = string_array_from_driver_info(mem_ctx,
5343                                                driver->core_driver_dependencies,
5344                                                &r->core_driver_dependencies,
5345                                                NULL, NULL, 0);
5346         if (!W_ERROR_IS_OK(result)) {
5347                 return result;
5348         }
5349
5350         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5351         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5352
5353         return WERR_OK;
5354 }
5355
5356 #if 0 /* disabled until marshalling issues are resolved - gd */
5357 /********************************************************************
5358  ********************************************************************/
5359
5360 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5361                                           struct spoolss_DriverFileInfo *r,
5362                                           const char *cservername,
5363                                           const char *file_name,
5364                                           enum spoolss_DriverFileType file_type,
5365                                           uint32_t file_version)
5366 {
5367         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5368                                           cservername, file_name);
5369         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5370         r->file_type    = file_type;
5371         r->file_version = file_version;
5372
5373         return WERR_OK;
5374 }
5375
5376 /********************************************************************
5377  ********************************************************************/
5378
5379 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5380                                                  const struct spoolss_DriverInfo8 *driver,
5381                                                  const char *cservername,
5382                                                  struct spoolss_DriverFileInfo **info_p,
5383                                                  uint32_t *count_p)
5384 {
5385         struct spoolss_DriverFileInfo *info = NULL;
5386         uint32_t count = 0;
5387         WERROR result;
5388         uint32_t i;
5389
5390         *info_p = NULL;
5391         *count_p = 0;
5392
5393         if (strlen(driver->driver_path)) {
5394                 info = talloc_realloc(mem_ctx, info,
5395                                             struct spoolss_DriverFileInfo,
5396                                             count + 1);
5397                 W_ERROR_HAVE_NO_MEMORY(info);
5398                 result = fill_spoolss_DriverFileInfo(info,
5399                                                      &info[count],
5400                                                      cservername,
5401                                                      driver->driver_path,
5402                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5403                                                      0);
5404                 W_ERROR_NOT_OK_RETURN(result);
5405                 count++;
5406         }
5407
5408         if (strlen(driver->config_file)) {
5409                 info = talloc_realloc(mem_ctx, info,
5410                                             struct spoolss_DriverFileInfo,
5411                                             count + 1);
5412                 W_ERROR_HAVE_NO_MEMORY(info);
5413                 result = fill_spoolss_DriverFileInfo(info,
5414                                                      &info[count],
5415                                                      cservername,
5416                                                      driver->config_file,
5417                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5418                                                      0);
5419                 W_ERROR_NOT_OK_RETURN(result);
5420                 count++;
5421         }
5422
5423         if (strlen(driver->data_file)) {
5424                 info = talloc_realloc(mem_ctx, info,
5425                                             struct spoolss_DriverFileInfo,
5426                                             count + 1);
5427                 W_ERROR_HAVE_NO_MEMORY(info);
5428                 result = fill_spoolss_DriverFileInfo(info,
5429                                                      &info[count],
5430                                                      cservername,
5431                                                      driver->data_file,
5432                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5433                                                      0);
5434                 W_ERROR_NOT_OK_RETURN(result);
5435                 count++;
5436         }
5437
5438         if (strlen(driver->help_file)) {
5439                 info = talloc_realloc(mem_ctx, info,
5440                                             struct spoolss_DriverFileInfo,
5441                                             count + 1);
5442                 W_ERROR_HAVE_NO_MEMORY(info);
5443                 result = fill_spoolss_DriverFileInfo(info,
5444                                                      &info[count],
5445                                                      cservername,
5446                                                      driver->help_file,
5447                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5448                                                      0);
5449                 W_ERROR_NOT_OK_RETURN(result);
5450                 count++;
5451         }
5452
5453         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5454                 info = talloc_realloc(mem_ctx, info,
5455                                             struct spoolss_DriverFileInfo,
5456                                             count + 1);
5457                 W_ERROR_HAVE_NO_MEMORY(info);
5458                 result = fill_spoolss_DriverFileInfo(info,
5459                                                      &info[count],
5460                                                      cservername,
5461                                                      driver->dependent_files[i],
5462                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5463                                                      0);
5464                 W_ERROR_NOT_OK_RETURN(result);
5465                 count++;
5466         }
5467
5468         *info_p = info;
5469         *count_p = count;
5470
5471         return WERR_OK;
5472 }
5473
5474 /********************************************************************
5475  * fill a spoolss_DriverInfo101 struct
5476  ********************************************************************/
5477
5478 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5479                                           struct spoolss_DriverInfo101 *r,
5480                                           const struct spoolss_DriverInfo8 *driver,
5481                                           const char *servername)
5482 {
5483         const char *cservername = canon_servername(servername);
5484         WERROR result;
5485
5486         r->version              = driver->version;
5487
5488         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5489         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5490         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5491         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5492
5493         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5494                                                     cservername,
5495                                                     &r->file_info,
5496                                                     &r->file_count);
5497         if (!W_ERROR_IS_OK(result)) {
5498                 return result;
5499         }
5500
5501         FILL_DRIVER_STRING(mem_ctx,
5502                            driver->monitor_name,
5503                            r->monitor_name);
5504
5505         FILL_DRIVER_STRING(mem_ctx,
5506                            driver->default_datatype,
5507                            r->default_datatype);
5508
5509         result = string_array_from_driver_info(mem_ctx,
5510                                                driver->previous_names,
5511                                                &r->previous_names,
5512                                                NULL, NULL, 0);
5513         if (!W_ERROR_IS_OK(result)) {
5514                 return result;
5515         }
5516
5517         r->driver_date          = driver->driver_date;
5518         r->driver_version       = driver->driver_version;
5519
5520         FILL_DRIVER_STRING(mem_ctx,
5521                            driver->manufacturer_name,
5522                            r->manufacturer_name);
5523         FILL_DRIVER_STRING(mem_ctx,
5524                            driver->manufacturer_url,
5525                            r->manufacturer_url);
5526         FILL_DRIVER_STRING(mem_ctx,
5527                            driver->hardware_id,
5528                            r->hardware_id);
5529         FILL_DRIVER_STRING(mem_ctx,
5530                            driver->provider,
5531                            r->provider);
5532
5533         return WERR_OK;
5534 }
5535 #endif
5536 /********************************************************************
5537  ********************************************************************/
5538
5539 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5540                                                   const struct auth_session_info *session_info,
5541                                                   struct messaging_context *msg_ctx,
5542                                                   uint32_t level,
5543                                                   union spoolss_DriverInfo *r,
5544                                                   int snum,
5545                                                   const char *servername,
5546                                                   const char *architecture,
5547                                                   uint32_t version)
5548 {
5549         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5550         struct spoolss_DriverInfo8 *driver;
5551         WERROR result;
5552         struct dcerpc_binding_handle *b;
5553         TALLOC_CTX *tmp_ctx = NULL;
5554
5555         if (level == 101) {
5556                 return WERR_UNKNOWN_LEVEL;
5557         }
5558
5559         tmp_ctx = talloc_new(mem_ctx);
5560         if (!tmp_ctx) {
5561                 return WERR_NOMEM;
5562         }
5563
5564         result = winreg_printer_binding_handle(tmp_ctx,
5565                                                session_info,
5566                                                msg_ctx,
5567                                                &b);
5568         if (!W_ERROR_IS_OK(result)) {
5569                 goto done;
5570         }
5571
5572         result = winreg_get_printer(tmp_ctx, b,
5573                                     lp_const_servicename(snum),
5574                                     &pinfo2);
5575
5576         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5577                 win_errstr(result)));
5578
5579         if (!W_ERROR_IS_OK(result)) {
5580                 result = WERR_INVALID_PRINTER_NAME;
5581                 goto done;
5582         }
5583
5584         result = winreg_get_driver(tmp_ctx, b,
5585                                    architecture,
5586                                    pinfo2->drivername, version, &driver);
5587
5588         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5589                 win_errstr(result)));
5590
5591         if (!W_ERROR_IS_OK(result)) {
5592                 /*
5593                  * Is this a W2k client ?
5594                  */
5595
5596                 if (version < 3) {
5597                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5598                         goto done;
5599                 }
5600
5601                 /* Yes - try again with a WinNT driver. */
5602                 version = 2;
5603                 result = winreg_get_driver(tmp_ctx, b,
5604                                            architecture,
5605                                            pinfo2->drivername,
5606                                            version, &driver);
5607                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5608                         win_errstr(result)));
5609                 if (!W_ERROR_IS_OK(result)) {
5610                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5611                         goto done;
5612                 }
5613         }
5614
5615         /* these are allocated on mem_ctx and not tmp_ctx because they are
5616          * the 'return value' and need to utlive this call */
5617         switch (level) {
5618         case 1:
5619                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5620                 break;
5621         case 2:
5622                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5623                 break;
5624         case 3:
5625                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5626                 break;
5627         case 4:
5628                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5629                 break;
5630         case 5:
5631                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5632                 break;
5633         case 6:
5634                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5635                 break;
5636         case 8:
5637                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5638                 break;
5639 #if 0 /* disabled until marshalling issues are resolved - gd */
5640         case 101:
5641                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5642                 break;
5643 #endif
5644         default:
5645                 result = WERR_UNKNOWN_LEVEL;
5646                 break;
5647         }
5648
5649 done:
5650         talloc_free(tmp_ctx);
5651         return result;
5652 }
5653
5654 /****************************************************************
5655  _spoolss_GetPrinterDriver2
5656 ****************************************************************/
5657
5658 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5659                                   struct spoolss_GetPrinterDriver2 *r)
5660 {
5661         struct printer_handle *printer;
5662         WERROR result;
5663
5664         int snum;
5665
5666         /* that's an [in out] buffer */
5667
5668         if (!r->in.buffer && (r->in.offered != 0)) {
5669                 return WERR_INVALID_PARAM;
5670         }
5671
5672         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5673
5674         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5675                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5676                 return WERR_INVALID_PRINTER_NAME;
5677         }
5678
5679         *r->out.needed = 0;
5680         *r->out.server_major_version = 0;
5681         *r->out.server_minor_version = 0;
5682
5683         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5684                 return WERR_BADFID;
5685         }
5686
5687         result = construct_printer_driver_info_level(p->mem_ctx,
5688                                                      get_session_info_system(),
5689                                                      p->msg_ctx,
5690                                                      r->in.level, r->out.info,
5691                                                      snum, printer->servername,
5692                                                      r->in.architecture,
5693                                                      r->in.client_major_version);
5694         if (!W_ERROR_IS_OK(result)) {
5695                 TALLOC_FREE(r->out.info);
5696                 return result;
5697         }
5698
5699         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5700                                                r->out.info, r->in.level);
5701         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5702
5703         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5704 }
5705
5706
5707 /****************************************************************
5708  _spoolss_StartPagePrinter
5709 ****************************************************************/
5710
5711 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5712                                  struct spoolss_StartPagePrinter *r)
5713 {
5714         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5715
5716         if (!Printer) {
5717                 DEBUG(3,("_spoolss_StartPagePrinter: "
5718                         "Error in startpageprinter printer handle\n"));
5719                 return WERR_BADFID;
5720         }
5721
5722         Printer->page_started = true;
5723         return WERR_OK;
5724 }
5725
5726 /****************************************************************
5727  _spoolss_EndPagePrinter
5728 ****************************************************************/
5729
5730 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5731                                struct spoolss_EndPagePrinter *r)
5732 {
5733         int snum;
5734
5735         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5736
5737         if (!Printer) {
5738                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5739                         OUR_HANDLE(r->in.handle)));
5740                 return WERR_BADFID;
5741         }
5742
5743         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5744                 return WERR_BADFID;
5745
5746         Printer->page_started = false;
5747         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5748
5749         return WERR_OK;
5750 }
5751
5752 /****************************************************************
5753  _spoolss_StartDocPrinter
5754 ****************************************************************/
5755
5756 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5757                                 struct spoolss_StartDocPrinter *r)
5758 {
5759         struct spoolss_DocumentInfo1 *info_1;
5760         int snum;
5761         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5762         WERROR werr;
5763         char *rhost;
5764         int rc;
5765
5766         if (!Printer) {
5767                 DEBUG(2,("_spoolss_StartDocPrinter: "
5768                         "Invalid handle (%s:%u:%u)\n",
5769                         OUR_HANDLE(r->in.handle)));
5770                 return WERR_BADFID;
5771         }
5772
5773         if (Printer->jobid) {
5774                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5775                           "StartDocPrinter called twice! "
5776                           "(existing jobid = %d)\n", Printer->jobid));
5777                 return WERR_INVALID_HANDLE;
5778         }
5779
5780         if (r->in.level != 1) {
5781                 return WERR_UNKNOWN_LEVEL;
5782         }
5783
5784         info_1 = r->in.info.info1;
5785
5786         /*
5787          * a nice thing with NT is it doesn't listen to what you tell it.
5788          * when asked to send _only_ RAW datas, it tries to send datas
5789          * in EMF format.
5790          *
5791          * So I add checks like in NT Server ...
5792          */
5793
5794         if (info_1->datatype) {
5795                 if (strcmp(info_1->datatype, "RAW") != 0) {
5796                         *r->out.job_id = 0;
5797                         return WERR_INVALID_DATATYPE;
5798                 }
5799         }
5800
5801         /* get the share number of the printer */
5802         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5803                 return WERR_BADFID;
5804         }
5805
5806         rc = get_remote_hostname(p->remote_address,
5807                                  &rhost,
5808                                  p->mem_ctx);
5809         if (rc < 0) {
5810                 return WERR_NOMEM;
5811         }
5812         if (strequal(rhost,"UNKNOWN")) {
5813                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5814                                                          p->mem_ctx);
5815                 if (rhost == NULL) {
5816                         return WERR_NOMEM;
5817                 }
5818         }
5819
5820         werr = print_job_start(p->session_info,
5821                                p->msg_ctx,
5822                                rhost,
5823                                snum,
5824                                info_1->document_name,
5825                                info_1->output_file,
5826                                Printer->devmode,
5827                                &Printer->jobid);
5828
5829         /* An error occured in print_job_start() so return an appropriate
5830            NT error code. */
5831
5832         if (!W_ERROR_IS_OK(werr)) {
5833                 return werr;
5834         }
5835
5836         Printer->document_started = true;
5837         *r->out.job_id = Printer->jobid;
5838
5839         return WERR_OK;
5840 }
5841
5842 /****************************************************************
5843  _spoolss_EndDocPrinter
5844 ****************************************************************/
5845
5846 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5847                               struct spoolss_EndDocPrinter *r)
5848 {
5849         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5850         NTSTATUS status;
5851         int snum;
5852
5853         if (!Printer) {
5854                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5855                         OUR_HANDLE(r->in.handle)));
5856                 return WERR_BADFID;
5857         }
5858
5859         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5860                 return WERR_BADFID;
5861         }
5862
5863         Printer->document_started = false;
5864         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5865         if (!NT_STATUS_IS_OK(status)) {
5866                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5867                           "print_job_end failed [%s]\n",
5868                           nt_errstr(status)));
5869         }
5870
5871         Printer->jobid = 0;
5872         return ntstatus_to_werror(status);
5873 }
5874
5875 /****************************************************************
5876  _spoolss_WritePrinter
5877 ****************************************************************/
5878
5879 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5880                              struct spoolss_WritePrinter *r)
5881 {
5882         ssize_t buffer_written;
5883         int snum;
5884         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5885
5886         if (!Printer) {
5887                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5888                         OUR_HANDLE(r->in.handle)));
5889                 *r->out.num_written = r->in._data_size;
5890                 return WERR_BADFID;
5891         }
5892
5893         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5894                 return WERR_BADFID;
5895
5896         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5897         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5898                                                    snum, Printer->jobid,
5899                                                    (const char *)r->in.data.data,
5900                                                    (size_t)r->in._data_size);
5901         if (buffer_written == (ssize_t)-1) {
5902                 *r->out.num_written = 0;
5903                 if (errno == ENOSPC)
5904                         return WERR_NO_SPOOL_SPACE;
5905                 else
5906                         return WERR_ACCESS_DENIED;
5907         }
5908
5909         *r->out.num_written = r->in._data_size;
5910
5911         return WERR_OK;
5912 }
5913
5914 /********************************************************************
5915  * api_spoolss_getprinter
5916  * called from the spoolss dispatcher
5917  *
5918  ********************************************************************/
5919
5920 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5921                               struct pipes_struct *p)
5922 {
5923         const struct auth_session_info *session_info = p->session_info;
5924         int snum;
5925         WERROR errcode = WERR_BADFUNC;
5926         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5927
5928         if (!Printer) {
5929                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5930                         OUR_HANDLE(handle)));
5931                 return WERR_BADFID;
5932         }
5933
5934         if (!get_printer_snum(p, handle, &snum, NULL))
5935                 return WERR_BADFID;
5936
5937         switch (command) {
5938         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5939                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5940                 break;
5941         case SPOOLSS_PRINTER_CONTROL_RESUME:
5942         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5943                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5944                 break;
5945         case SPOOLSS_PRINTER_CONTROL_PURGE:
5946                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5947                 break;
5948         default:
5949                 return WERR_UNKNOWN_LEVEL;
5950         }
5951
5952         return errcode;
5953 }
5954
5955
5956 /****************************************************************
5957  _spoolss_AbortPrinter
5958  * From MSDN: "Deletes printer's spool file if printer is configured
5959  * for spooling"
5960 ****************************************************************/
5961
5962 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5963                              struct spoolss_AbortPrinter *r)
5964 {
5965         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5966         int             snum;
5967         WERROR          errcode = WERR_OK;
5968
5969         if (!Printer) {
5970                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5971                         OUR_HANDLE(r->in.handle)));
5972                 return WERR_BADFID;
5973         }
5974
5975         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5976                 return WERR_BADFID;
5977
5978         if (!Printer->document_started) {
5979                 return WERR_SPL_NO_STARTDOC;
5980         }
5981
5982         errcode = print_job_delete(p->session_info,
5983                                    p->msg_ctx,
5984                                    snum,
5985                                    Printer->jobid);
5986
5987         return errcode;
5988 }
5989
5990 /********************************************************************
5991  * called by spoolss_api_setprinter
5992  * when updating a printer description
5993  ********************************************************************/
5994
5995 static WERROR update_printer_sec(struct policy_handle *handle,
5996                                  struct pipes_struct *p,
5997                                  struct sec_desc_buf *secdesc_ctr)
5998 {
5999         struct spoolss_security_descriptor *new_secdesc = NULL;
6000         struct spoolss_security_descriptor *old_secdesc = NULL;
6001         const char *printer;
6002         WERROR result;
6003         int snum;
6004         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6005         struct dcerpc_binding_handle *b;
6006         TALLOC_CTX *tmp_ctx = NULL;
6007
6008         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6009                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6010                          OUR_HANDLE(handle)));
6011
6012                 result = WERR_BADFID;
6013                 goto done;
6014         }
6015
6016         if (secdesc_ctr == NULL) {
6017                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6018                 result = WERR_INVALID_PARAM;
6019                 goto done;
6020         }
6021         printer = lp_const_servicename(snum);
6022
6023         /* Check the user has permissions to change the security
6024            descriptor.  By experimentation with two NT machines, the user
6025            requires Full Access to the printer to change security
6026            information. */
6027
6028         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6029                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6030                 result = WERR_ACCESS_DENIED;
6031                 goto done;
6032         }
6033
6034         tmp_ctx = talloc_new(p->mem_ctx);
6035         if (!tmp_ctx) {
6036                 return WERR_NOMEM;
6037         }
6038
6039         result = winreg_printer_binding_handle(tmp_ctx,
6040                                                get_session_info_system(),
6041                                                p->msg_ctx,
6042                                                &b);
6043         if (!W_ERROR_IS_OK(result)) {
6044                 goto done;
6045         }
6046
6047         /* NT seems to like setting the security descriptor even though
6048            nothing may have actually changed. */
6049         result = winreg_get_printer_secdesc(tmp_ctx, b,
6050                                             printer,
6051                                             &old_secdesc);
6052         if (!W_ERROR_IS_OK(result)) {
6053                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6054                 result = WERR_BADFID;
6055                 goto done;
6056         }
6057
6058         if (DEBUGLEVEL >= 10) {
6059                 struct security_acl *the_acl;
6060                 int i;
6061
6062                 the_acl = old_secdesc->dacl;
6063                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6064                            printer, the_acl->num_aces));
6065
6066                 for (i = 0; i < the_acl->num_aces; i++) {
6067                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6068                                            &the_acl->aces[i].trustee),
6069                                   the_acl->aces[i].access_mask));
6070                 }
6071
6072                 the_acl = secdesc_ctr->sd->dacl;
6073
6074                 if (the_acl) {
6075                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6076                                    printer, the_acl->num_aces));
6077
6078                         for (i = 0; i < the_acl->num_aces; i++) {
6079                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6080                                                    &the_acl->aces[i].trustee),
6081                                            the_acl->aces[i].access_mask));
6082                         }
6083                 } else {
6084                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6085                 }
6086         }
6087
6088         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6089         if (new_secdesc == NULL) {
6090                 result = WERR_NOMEM;
6091                 goto done;
6092         }
6093
6094         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6095                 result = WERR_OK;
6096                 goto done;
6097         }
6098
6099         result = winreg_set_printer_secdesc(tmp_ctx, b,
6100                                             printer,
6101                                             new_secdesc);
6102
6103 done:
6104         talloc_free(tmp_ctx);
6105         return result;
6106 }
6107
6108 /********************************************************************
6109  Canonicalize printer info from a client
6110  ********************************************************************/
6111
6112 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6113                              struct spoolss_SetPrinterInfo2 *info2,
6114                              int snum)
6115 {
6116         fstring printername;
6117         const char *p;
6118
6119         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6120                 "portname=%s drivername=%s comment=%s location=%s\n",
6121                 info2->servername, info2->printername, info2->sharename,
6122                 info2->portname, info2->drivername, info2->comment,
6123                 info2->location));
6124
6125         /* we force some elements to "correct" values */
6126         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6127         if (info2->servername == NULL) {
6128                 return false;
6129         }
6130         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6131         if (info2->sharename == NULL) {
6132                 return false;
6133         }
6134
6135         /* check to see if we allow printername != sharename */
6136         if (lp_force_printername(snum)) {
6137                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6138                                         lp_netbios_name(), info2->sharename);
6139         } else {
6140                 /* make sure printername is in \\server\printername format */
6141                 fstrcpy(printername, info2->printername);
6142                 p = printername;
6143                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6144                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6145                                 p++;
6146                 }
6147
6148                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6149                                         lp_netbios_name(), p);
6150         }
6151         if (info2->printername == NULL) {
6152                 return false;
6153         }
6154
6155         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6156         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6157
6158         return true;
6159 }
6160
6161 /****************************************************************************
6162 ****************************************************************************/
6163
6164 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6165 {
6166         char *cmd = lp_addport_cmd();
6167         char *command = NULL;
6168         int ret;
6169         bool is_print_op = false;
6170
6171         if ( !*cmd ) {
6172                 return WERR_ACCESS_DENIED;
6173         }
6174
6175         command = talloc_asprintf(ctx,
6176                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6177         if (!command) {
6178                 return WERR_NOMEM;
6179         }
6180
6181         if ( token )
6182                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6183
6184         DEBUG(10,("Running [%s]\n", command));
6185
6186         /********* BEGIN SePrintOperatorPrivilege **********/
6187
6188         if ( is_print_op )
6189                 become_root();
6190
6191         ret = smbrun(command, NULL);
6192
6193         if ( is_print_op )
6194                 unbecome_root();
6195
6196         /********* END SePrintOperatorPrivilege **********/
6197
6198         DEBUGADD(10,("returned [%d]\n", ret));
6199
6200         TALLOC_FREE(command);
6201
6202         if ( ret != 0 ) {
6203                 return WERR_ACCESS_DENIED;
6204         }
6205
6206         return WERR_OK;
6207 }
6208
6209 /****************************************************************************
6210 ****************************************************************************/
6211
6212 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6213                              struct spoolss_SetPrinterInfo2 *info2,
6214                              const char *remote_machine,
6215                              struct messaging_context *msg_ctx)
6216 {
6217         char *cmd = lp_addprinter_cmd();
6218         char **qlines;
6219         char *command = NULL;
6220         int numlines;
6221         int ret;
6222         int fd;
6223         bool is_print_op = false;
6224
6225         if (!remote_machine) {
6226                 return false;
6227         }
6228
6229         command = talloc_asprintf(ctx,
6230                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6231                         cmd, info2->printername, info2->sharename,
6232                         info2->portname, info2->drivername,
6233                         info2->location, info2->comment, remote_machine);
6234         if (!command) {
6235                 return false;
6236         }
6237
6238         if ( token )
6239                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6240
6241         DEBUG(10,("Running [%s]\n", command));
6242
6243         /********* BEGIN SePrintOperatorPrivilege **********/
6244
6245         if ( is_print_op )
6246                 become_root();
6247
6248         if ( (ret = smbrun(command, &fd)) == 0 ) {
6249                 /* Tell everyone we updated smb.conf. */
6250                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6251         }
6252
6253         if ( is_print_op )
6254                 unbecome_root();
6255
6256         /********* END SePrintOperatorPrivilege **********/
6257
6258         DEBUGADD(10,("returned [%d]\n", ret));
6259
6260         TALLOC_FREE(command);
6261
6262         if ( ret != 0 ) {
6263                 if (fd != -1)
6264                         close(fd);
6265                 return false;
6266         }
6267
6268         /* reload our services immediately */
6269         become_root();
6270         reload_services(msg_ctx, -1, false);
6271         unbecome_root();
6272
6273         numlines = 0;
6274         /* Get lines and convert them back to dos-codepage */
6275         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6276         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6277         close(fd);
6278
6279         /* Set the portname to what the script says the portname should be. */
6280         /* but don't require anything to be return from the script exit a good error code */
6281
6282         if (numlines) {
6283                 /* Set the portname to what the script says the portname should be. */
6284                 info2->portname = talloc_strdup(ctx, qlines[0]);
6285                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6286         }
6287
6288         TALLOC_FREE(qlines);
6289         return true;
6290 }
6291
6292 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6293                                const struct auth_session_info *session_info,
6294                                struct messaging_context *msg_ctx,
6295                                int snum,
6296                                struct spoolss_SetPrinterInfo2 *printer,
6297                                struct spoolss_PrinterInfo2 *old_printer)
6298 {
6299         bool force_update = (old_printer == NULL);
6300         const char *dnsdomname;
6301         const char *longname;
6302         const char *uncname;
6303         const char *spooling;
6304         DATA_BLOB buffer;
6305         WERROR result = WERR_OK;
6306         struct dcerpc_binding_handle *b;
6307         TALLOC_CTX *tmp_ctx;
6308
6309         tmp_ctx = talloc_new(mem_ctx);
6310         if (!tmp_ctx) {
6311                 return WERR_NOMEM;
6312         }
6313
6314         result = winreg_printer_binding_handle(tmp_ctx,
6315                                                session_info,
6316                                                msg_ctx,
6317                                                &b);
6318         if (!W_ERROR_IS_OK(result)) {
6319                 goto done;
6320         }
6321
6322         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6323                 push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6324                 winreg_set_printer_dataex(tmp_ctx, b,
6325                                           printer->sharename,
6326                                           SPOOL_DSSPOOLER_KEY,
6327                                           SPOOL_REG_DRIVERNAME,
6328                                           REG_SZ,
6329                                           buffer.data,
6330                                           buffer.length);
6331
6332                 if (!force_update) {
6333                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6334                                 printer->drivername));
6335
6336                         notify_printer_driver(server_event_context(), msg_ctx,
6337                                               snum, printer->drivername ?
6338                                               printer->drivername : "");
6339                 }
6340         }
6341
6342         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6343                 push_reg_sz(tmp_ctx, &buffer, printer->comment);
6344                 winreg_set_printer_dataex(tmp_ctx, b,
6345                                           printer->sharename,
6346                                           SPOOL_DSSPOOLER_KEY,
6347                                           SPOOL_REG_DESCRIPTION,
6348                                           REG_SZ,
6349                                           buffer.data,
6350                                           buffer.length);
6351
6352                 if (!force_update) {
6353                         notify_printer_comment(server_event_context(), msg_ctx,
6354                                                snum, printer->comment ?
6355                                                printer->comment : "");
6356                 }
6357         }
6358
6359         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6360                 push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6361                 winreg_set_printer_dataex(tmp_ctx, b,
6362                                           printer->sharename,
6363                                           SPOOL_DSSPOOLER_KEY,
6364                                           SPOOL_REG_PRINTSHARENAME,
6365                                           REG_SZ,
6366                                           buffer.data,
6367                                           buffer.length);
6368
6369                 if (!force_update) {
6370                         notify_printer_sharename(server_event_context(),
6371                                                  msg_ctx,
6372                                                  snum, printer->sharename ?
6373                                                  printer->sharename : "");
6374                 }
6375         }
6376
6377         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6378                 const char *p;
6379
6380                 p = strrchr(printer->printername, '\\' );
6381                 if (p != NULL) {
6382                         p++;
6383                 } else {
6384                         p = printer->printername;
6385                 }
6386
6387                 push_reg_sz(tmp_ctx, &buffer, p);
6388                 winreg_set_printer_dataex(tmp_ctx, b,
6389                                           printer->sharename,
6390                                           SPOOL_DSSPOOLER_KEY,
6391                                           SPOOL_REG_PRINTERNAME,
6392                                           REG_SZ,
6393                                           buffer.data,
6394                                           buffer.length);
6395
6396                 if (!force_update) {
6397                         notify_printer_printername(server_event_context(),
6398                                                    msg_ctx, snum, p ? p : "");
6399                 }
6400         }
6401
6402         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6403                 push_reg_sz(tmp_ctx, &buffer, printer->portname);
6404                 winreg_set_printer_dataex(tmp_ctx, b,
6405                                           printer->sharename,
6406                                           SPOOL_DSSPOOLER_KEY,
6407                                           SPOOL_REG_PORTNAME,
6408                                           REG_SZ,
6409                                           buffer.data,
6410                                           buffer.length);
6411
6412                 if (!force_update) {
6413                         notify_printer_port(server_event_context(),
6414                                             msg_ctx, snum, printer->portname ?
6415                                             printer->portname : "");
6416                 }
6417         }
6418
6419         if (force_update || !strequal(printer->location, old_printer->location)) {
6420                 push_reg_sz(tmp_ctx, &buffer, printer->location);
6421                 winreg_set_printer_dataex(tmp_ctx, b,
6422                                           printer->sharename,
6423                                           SPOOL_DSSPOOLER_KEY,
6424                                           SPOOL_REG_LOCATION,
6425                                           REG_SZ,
6426                                           buffer.data,
6427                                           buffer.length);
6428
6429                 if (!force_update) {
6430                         notify_printer_location(server_event_context(),
6431                                                 msg_ctx, snum,
6432                                                 printer->location ?
6433                                                 printer->location : "");
6434                 }
6435         }
6436
6437         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6438                 push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6439                 winreg_set_printer_dataex(tmp_ctx, b,
6440                                           printer->sharename,
6441                                           SPOOL_DSSPOOLER_KEY,
6442                                           SPOOL_REG_PRINTSEPARATORFILE,
6443                                           REG_SZ,
6444                                           buffer.data,
6445                                           buffer.length);
6446
6447                 if (!force_update) {
6448                         notify_printer_sepfile(server_event_context(),
6449                                                msg_ctx, snum,
6450                                                printer->sepfile ?
6451                                                printer->sepfile : "");
6452                 }
6453         }
6454
6455         if (force_update || printer->starttime != old_printer->starttime) {
6456                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6457                 SIVAL(buffer.data, 0, printer->starttime);
6458                 winreg_set_printer_dataex(tmp_ctx, b,
6459                                           printer->sharename,
6460                                           SPOOL_DSSPOOLER_KEY,
6461                                           SPOOL_REG_PRINTSTARTTIME,
6462                                           REG_DWORD,
6463                                           buffer.data,
6464                                           buffer.length);
6465         }
6466
6467         if (force_update || printer->untiltime != old_printer->untiltime) {
6468                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6469                 SIVAL(buffer.data, 0, printer->untiltime);
6470                 winreg_set_printer_dataex(tmp_ctx, b,
6471                                           printer->sharename,
6472                                           SPOOL_DSSPOOLER_KEY,
6473                                           SPOOL_REG_PRINTENDTIME,
6474                                           REG_DWORD,
6475                                           buffer.data,
6476                                           buffer.length);
6477         }
6478
6479         if (force_update || printer->priority != old_printer->priority) {
6480                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6481                 SIVAL(buffer.data, 0, printer->priority);
6482                 winreg_set_printer_dataex(tmp_ctx, b,
6483                                           printer->sharename,
6484                                           SPOOL_DSSPOOLER_KEY,
6485                                           SPOOL_REG_PRIORITY,
6486                                           REG_DWORD,
6487                                           buffer.data,
6488                                           buffer.length);
6489         }
6490
6491         if (force_update || printer->attributes != old_printer->attributes) {
6492                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6493                 SIVAL(buffer.data, 0, (printer->attributes &
6494                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6495                 winreg_set_printer_dataex(tmp_ctx, b,
6496                                           printer->sharename,
6497                                           SPOOL_DSSPOOLER_KEY,
6498                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6499                                           REG_DWORD,
6500                                           buffer.data,
6501                                           buffer.length);
6502
6503                 switch (printer->attributes & 0x3) {
6504                         case 0:
6505                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6506                                 break;
6507                         case 1:
6508                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6509                                 break;
6510                         case 2:
6511                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6512                                 break;
6513                         default:
6514                                 spooling = "unknown";
6515                 }
6516                 push_reg_sz(tmp_ctx, &buffer, spooling);
6517                 winreg_set_printer_dataex(tmp_ctx, b,
6518                                           printer->sharename,
6519                                           SPOOL_DSSPOOLER_KEY,
6520                                           SPOOL_REG_PRINTSPOOLING,
6521                                           REG_SZ,
6522                                           buffer.data,
6523                                           buffer.length);
6524         }
6525
6526         push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6527         winreg_set_printer_dataex(tmp_ctx, b,
6528                                   printer->sharename,
6529                                   SPOOL_DSSPOOLER_KEY,
6530                                   SPOOL_REG_SHORTSERVERNAME,
6531                                   REG_SZ,
6532                                   buffer.data,
6533                                   buffer.length);
6534
6535         dnsdomname = get_mydnsfullname();
6536         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6537                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6538         } else {
6539                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6540         }
6541         if (longname == NULL) {
6542                 result = WERR_NOMEM;
6543                 goto done;
6544         }
6545
6546         push_reg_sz(tmp_ctx, &buffer, longname);
6547         winreg_set_printer_dataex(tmp_ctx, b,
6548                                   printer->sharename,
6549                                   SPOOL_DSSPOOLER_KEY,
6550                                   SPOOL_REG_SERVERNAME,
6551                                   REG_SZ,
6552                                   buffer.data,
6553                                   buffer.length);
6554
6555         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6556                                   lp_netbios_name(), printer->sharename);
6557         push_reg_sz(tmp_ctx, &buffer, uncname);
6558         winreg_set_printer_dataex(tmp_ctx, b,
6559                                   printer->sharename,
6560                                   SPOOL_DSSPOOLER_KEY,
6561                                   SPOOL_REG_UNCNAME,
6562                                   REG_SZ,
6563                                   buffer.data,
6564                                   buffer.length);
6565
6566 done:
6567         talloc_free(tmp_ctx);
6568         return result;
6569 }
6570
6571 /********************************************************************
6572  * Called by spoolss_api_setprinter
6573  * when updating a printer description.
6574  ********************************************************************/
6575
6576 static WERROR update_printer(struct pipes_struct *p,
6577                              struct policy_handle *handle,
6578                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6579                              struct spoolss_DeviceMode *devmode)
6580 {
6581         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6582         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6583         struct spoolss_PrinterInfo2 *old_printer;
6584         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6585         int snum;
6586         WERROR result = WERR_OK;
6587         TALLOC_CTX *tmp_ctx;
6588         struct dcerpc_binding_handle *b;
6589
6590         DEBUG(8,("update_printer\n"));
6591
6592         tmp_ctx = talloc_new(p->mem_ctx);
6593         if (tmp_ctx == NULL) {
6594                 return WERR_NOMEM;
6595         }
6596
6597         if (!Printer) {
6598                 result = WERR_BADFID;
6599                 goto done;
6600         }
6601
6602         if (!get_printer_snum(p, handle, &snum, NULL)) {
6603                 result = WERR_BADFID;
6604                 goto done;
6605         }
6606
6607         result = winreg_printer_binding_handle(tmp_ctx,
6608                                                get_session_info_system(),
6609                                                p->msg_ctx,
6610                                                &b);
6611         if (!W_ERROR_IS_OK(result)) {
6612                 goto done;
6613         }
6614
6615         result = winreg_get_printer(tmp_ctx, b,
6616                                     lp_const_servicename(snum),
6617                                     &old_printer);
6618         if (!W_ERROR_IS_OK(result)) {
6619                 result = WERR_BADFID;
6620                 goto done;
6621         }
6622
6623         /* Do sanity check on the requested changes for Samba */
6624         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6625                 result = WERR_INVALID_PARAM;
6626                 goto done;
6627         }
6628
6629         /* FIXME!!! If the driver has changed we really should verify that
6630            it is installed before doing much else   --jerry */
6631
6632         /* Check calling user has permission to update printer description */
6633         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6634                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6635                 result = WERR_ACCESS_DENIED;
6636                 goto done;
6637         }
6638
6639         /* Call addprinter hook */
6640         /* Check changes to see if this is really needed */
6641
6642         if (*lp_addprinter_cmd() &&
6643                         (!strequal(printer->drivername, old_printer->drivername) ||
6644                          !strequal(printer->comment, old_printer->comment) ||
6645                          !strequal(printer->portname, old_printer->portname) ||
6646                          !strequal(printer->location, old_printer->location)) )
6647         {
6648                 char *raddr;
6649
6650                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6651                                                          p->mem_ctx);
6652                 if (raddr == NULL) {
6653                         return WERR_NOMEM;
6654                 }
6655
6656                 /* add_printer_hook() will call reload_services() */
6657                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6658                                       printer, raddr,
6659                                       p->msg_ctx)) {
6660                         result = WERR_ACCESS_DENIED;
6661                         goto done;
6662                 }
6663         }
6664
6665         update_dsspooler(tmp_ctx,
6666                          get_session_info_system(),
6667                          p->msg_ctx,
6668                          snum,
6669                          printer,
6670                          old_printer);
6671
6672         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6673
6674         if (devmode == NULL) {
6675                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6676         }
6677         result = winreg_update_printer(tmp_ctx, b,
6678                                        printer->sharename,
6679                                        printer_mask,
6680                                        printer,
6681                                        devmode,
6682                                        NULL);
6683
6684 done:
6685         talloc_free(tmp_ctx);
6686
6687         return result;
6688 }
6689
6690 /****************************************************************************
6691 ****************************************************************************/
6692 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6693                                            struct policy_handle *handle,
6694                                            struct spoolss_SetPrinterInfo7 *info7)
6695 {
6696 #ifdef HAVE_ADS
6697         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6698         WERROR result;
6699         int snum;
6700         struct printer_handle *Printer;
6701
6702         if ( lp_security() != SEC_ADS ) {
6703                 return WERR_UNKNOWN_LEVEL;
6704         }
6705
6706         Printer = find_printer_index_by_hnd(p, handle);
6707
6708         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6709
6710         if (!Printer)
6711                 return WERR_BADFID;
6712
6713         if (!get_printer_snum(p, handle, &snum, NULL))
6714                 return WERR_BADFID;
6715
6716         result = winreg_get_printer_internal(p->mem_ctx,
6717                                     get_session_info_system(),
6718                                     p->msg_ctx,
6719                                     lp_servicename(snum),
6720                                     &pinfo2);
6721         if (!W_ERROR_IS_OK(result)) {
6722                 return WERR_BADFID;
6723         }
6724
6725         nt_printer_publish(pinfo2,
6726                            get_session_info_system(),
6727                            p->msg_ctx,
6728                            pinfo2,
6729                            info7->action);
6730
6731         TALLOC_FREE(pinfo2);
6732         return WERR_OK;
6733 #else
6734         return WERR_UNKNOWN_LEVEL;
6735 #endif
6736 }
6737
6738 /********************************************************************
6739  ********************************************************************/
6740
6741 static WERROR update_printer_devmode(struct pipes_struct *p,
6742                                      struct policy_handle *handle,
6743                                      struct spoolss_DeviceMode *devmode)
6744 {
6745         int snum;
6746         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6747         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6748
6749         DEBUG(8,("update_printer_devmode\n"));
6750
6751         if (!Printer) {
6752                 return WERR_BADFID;
6753         }
6754
6755         if (!get_printer_snum(p, handle, &snum, NULL)) {
6756                 return WERR_BADFID;
6757         }
6758
6759         /* Check calling user has permission to update printer description */
6760         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6761                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6762                 return WERR_ACCESS_DENIED;
6763         }
6764
6765         return winreg_update_printer_internal(p->mem_ctx,
6766                                      get_session_info_system(),
6767                                      p->msg_ctx,
6768                                      lp_const_servicename(snum),
6769                                      info2_mask,
6770                                      NULL,
6771                                      devmode,
6772                                      NULL);
6773 }
6774
6775
6776 /****************************************************************
6777  _spoolss_SetPrinter
6778 ****************************************************************/
6779
6780 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6781                            struct spoolss_SetPrinter *r)
6782 {
6783         WERROR result;
6784
6785         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6786
6787         if (!Printer) {
6788                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6789                         OUR_HANDLE(r->in.handle)));
6790                 return WERR_BADFID;
6791         }
6792
6793         /* check the level */
6794         switch (r->in.info_ctr->level) {
6795                 case 0:
6796                         return control_printer(r->in.handle, r->in.command, p);
6797                 case 2:
6798                         result = update_printer(p, r->in.handle,
6799                                                 r->in.info_ctr,
6800                                                 r->in.devmode_ctr->devmode);
6801                         if (!W_ERROR_IS_OK(result))
6802                                 return result;
6803                         if (r->in.secdesc_ctr->sd)
6804                                 result = update_printer_sec(r->in.handle, p,
6805                                                             r->in.secdesc_ctr);
6806                         return result;
6807                 case 3:
6808                         return update_printer_sec(r->in.handle, p,
6809                                                   r->in.secdesc_ctr);
6810                 case 7:
6811                         return publish_or_unpublish_printer(p, r->in.handle,
6812                                                             r->in.info_ctr->info.info7);
6813                 case 8:
6814                         return update_printer_devmode(p, r->in.handle,
6815                                                       r->in.devmode_ctr->devmode);
6816                 default:
6817                         return WERR_UNKNOWN_LEVEL;
6818         }
6819 }
6820
6821 /****************************************************************
6822  _spoolss_FindClosePrinterNotify
6823 ****************************************************************/
6824
6825 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6826                                        struct spoolss_FindClosePrinterNotify *r)
6827 {
6828         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6829
6830         if (!Printer) {
6831                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6832                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6833                 return WERR_BADFID;
6834         }
6835
6836         if (Printer->notify.cli_chan != NULL &&
6837             Printer->notify.cli_chan->active_connections > 0) {
6838                 int snum = -1;
6839
6840                 if (Printer->printer_type == SPLHND_PRINTER) {
6841                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6842                                 return WERR_BADFID;
6843                         }
6844                 }
6845
6846                 srv_spoolss_replycloseprinter(snum, Printer);
6847         }
6848
6849         Printer->notify.flags=0;
6850         Printer->notify.options=0;
6851         Printer->notify.localmachine[0]='\0';
6852         Printer->notify.printerlocal=0;
6853         TALLOC_FREE(Printer->notify.option);
6854
6855         return WERR_OK;
6856 }
6857
6858 /****************************************************************
6859  _spoolss_AddJob
6860 ****************************************************************/
6861
6862 WERROR _spoolss_AddJob(struct pipes_struct *p,
6863                        struct spoolss_AddJob *r)
6864 {
6865         if (!r->in.buffer && (r->in.offered != 0)) {
6866                 return WERR_INVALID_PARAM;
6867         }
6868
6869         /* this is what a NT server returns for AddJob. AddJob must fail on
6870          * non-local printers */
6871
6872         if (r->in.level != 1) {
6873                 return WERR_UNKNOWN_LEVEL;
6874         }
6875
6876         return WERR_INVALID_PARAM;
6877 }
6878
6879 /****************************************************************************
6880 fill_job_info1
6881 ****************************************************************************/
6882
6883 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6884                              struct spoolss_JobInfo1 *r,
6885                              const print_queue_struct *queue,
6886                              int position, int snum,
6887                              struct spoolss_PrinterInfo2 *pinfo2)
6888 {
6889         struct tm *t;
6890
6891         t = gmtime(&queue->time);
6892
6893         r->job_id               = queue->job;
6894
6895         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6896         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6897         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6898         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6899         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6900         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6901         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6902         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6903         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6904         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6905         r->text_status          = talloc_strdup(mem_ctx, "");
6906         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6907
6908         r->status               = nt_printj_status(queue->status);
6909         r->priority             = queue->priority;
6910         r->position             = position;
6911         r->total_pages          = queue->page_count;
6912         r->pages_printed        = 0; /* ??? */
6913
6914         init_systemtime(&r->submitted, t);
6915
6916         return WERR_OK;
6917 }
6918
6919 /****************************************************************************
6920 fill_job_info2
6921 ****************************************************************************/
6922
6923 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6924                              struct spoolss_JobInfo2 *r,
6925                              const print_queue_struct *queue,
6926                              int position, int snum,
6927                              struct spoolss_PrinterInfo2 *pinfo2,
6928                              struct spoolss_DeviceMode *devmode)
6929 {
6930         struct tm *t;
6931
6932         t = gmtime(&queue->time);
6933
6934         r->job_id               = queue->job;
6935
6936         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6937         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6938         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6939         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6940         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6941         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6942         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6943         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6944         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6945         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6946         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6947         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6948         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6949         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6950         r->parameters           = talloc_strdup(mem_ctx, "");
6951         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6952         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6953         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6954
6955         r->devmode              = devmode;
6956
6957         r->text_status          = talloc_strdup(mem_ctx, "");
6958         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6959
6960         r->secdesc              = NULL;
6961
6962         r->status               = nt_printj_status(queue->status);
6963         r->priority             = queue->priority;
6964         r->position             = position;
6965         r->start_time           = 0;
6966         r->until_time           = 0;
6967         r->total_pages          = queue->page_count;
6968         r->size                 = queue->size;
6969         init_systemtime(&r->submitted, t);
6970         r->time                 = 0;
6971         r->pages_printed        = 0; /* ??? */
6972
6973         return WERR_OK;
6974 }
6975
6976 /****************************************************************************
6977 fill_job_info3
6978 ****************************************************************************/
6979
6980 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6981                              struct spoolss_JobInfo3 *r,
6982                              const print_queue_struct *queue,
6983                              const print_queue_struct *next_queue,
6984                              int position, int snum,
6985                              struct spoolss_PrinterInfo2 *pinfo2)
6986 {
6987         r->job_id               = queue->job;
6988         r->next_job_id          = 0;
6989         if (next_queue) {
6990                 r->next_job_id  = next_queue->job;
6991         }
6992         r->reserved             = 0;
6993
6994         return WERR_OK;
6995 }
6996
6997 /****************************************************************************
6998  Enumjobs at level 1.
6999 ****************************************************************************/
7000
7001 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7002                               const print_queue_struct *queue,
7003                               uint32_t num_queues, int snum,
7004                               struct spoolss_PrinterInfo2 *pinfo2,
7005                               union spoolss_JobInfo **info_p,
7006                               uint32_t *count)
7007 {
7008         union spoolss_JobInfo *info;
7009         int i;
7010         WERROR result = WERR_OK;
7011
7012         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7013         W_ERROR_HAVE_NO_MEMORY(info);
7014
7015         *count = num_queues;
7016
7017         for (i=0; i<*count; i++) {
7018                 result = fill_job_info1(info,
7019                                         &info[i].info1,
7020                                         &queue[i],
7021                                         i,
7022                                         snum,
7023                                         pinfo2);
7024                 if (!W_ERROR_IS_OK(result)) {
7025                         goto out;
7026                 }
7027         }
7028
7029  out:
7030         if (!W_ERROR_IS_OK(result)) {
7031                 TALLOC_FREE(info);
7032                 *count = 0;
7033                 return result;
7034         }
7035
7036         *info_p = info;
7037
7038         return WERR_OK;
7039 }
7040
7041 /****************************************************************************
7042  Enumjobs at level 2.
7043 ****************************************************************************/
7044
7045 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7046                               const print_queue_struct *queue,
7047                               uint32_t num_queues, int snum,
7048                               struct spoolss_PrinterInfo2 *pinfo2,
7049                               union spoolss_JobInfo **info_p,
7050                               uint32_t *count)
7051 {
7052         union spoolss_JobInfo *info;
7053         int i;
7054         WERROR result = WERR_OK;
7055
7056         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7057         W_ERROR_HAVE_NO_MEMORY(info);
7058
7059         *count = num_queues;
7060
7061         for (i=0; i<*count; i++) {
7062                 struct spoolss_DeviceMode *devmode;
7063
7064                 result = spoolss_create_default_devmode(info,
7065                                                         pinfo2->printername,
7066                                                         &devmode);
7067                 if (!W_ERROR_IS_OK(result)) {
7068                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7069                         goto out;
7070                 }
7071
7072                 result = fill_job_info2(info,
7073                                         &info[i].info2,
7074                                         &queue[i],
7075                                         i,
7076                                         snum,
7077                                         pinfo2,
7078                                         devmode);
7079                 if (!W_ERROR_IS_OK(result)) {
7080                         goto out;
7081                 }
7082         }
7083
7084  out:
7085         if (!W_ERROR_IS_OK(result)) {
7086                 TALLOC_FREE(info);
7087                 *count = 0;
7088                 return result;
7089         }
7090
7091         *info_p = info;
7092
7093         return WERR_OK;
7094 }
7095
7096 /****************************************************************************
7097  Enumjobs at level 3.
7098 ****************************************************************************/
7099
7100 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7101                               const print_queue_struct *queue,
7102                               uint32_t num_queues, int snum,
7103                               struct spoolss_PrinterInfo2 *pinfo2,
7104                               union spoolss_JobInfo **info_p,
7105                               uint32_t *count)
7106 {
7107         union spoolss_JobInfo *info;
7108         int i;
7109         WERROR result = WERR_OK;
7110
7111         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7112         W_ERROR_HAVE_NO_MEMORY(info);
7113
7114         *count = num_queues;
7115
7116         for (i=0; i<*count; i++) {
7117                 const print_queue_struct *next_queue = NULL;
7118
7119                 if (i+1 < *count) {
7120                         next_queue = &queue[i+1];
7121                 }
7122
7123                 result = fill_job_info3(info,
7124                                         &info[i].info3,
7125                                         &queue[i],
7126                                         next_queue,
7127                                         i,
7128                                         snum,
7129                                         pinfo2);
7130                 if (!W_ERROR_IS_OK(result)) {
7131                         goto out;
7132                 }
7133         }
7134
7135  out:
7136         if (!W_ERROR_IS_OK(result)) {
7137                 TALLOC_FREE(info);
7138                 *count = 0;
7139                 return result;
7140         }
7141
7142         *info_p = info;
7143
7144         return WERR_OK;
7145 }
7146
7147 /****************************************************************
7148  _spoolss_EnumJobs
7149 ****************************************************************/
7150
7151 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7152                          struct spoolss_EnumJobs *r)
7153 {
7154         WERROR result;
7155         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7156         int snum;
7157         print_status_struct prt_status;
7158         print_queue_struct *queue = NULL;
7159         uint32_t count;
7160
7161         /* that's an [in out] buffer */
7162
7163         if (!r->in.buffer && (r->in.offered != 0)) {
7164                 return WERR_INVALID_PARAM;
7165         }
7166
7167         DEBUG(4,("_spoolss_EnumJobs\n"));
7168
7169         *r->out.needed = 0;
7170         *r->out.count = 0;
7171         *r->out.info = NULL;
7172
7173         /* lookup the printer snum and tdb entry */
7174
7175         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7176                 return WERR_BADFID;
7177         }
7178
7179         result = winreg_get_printer_internal(p->mem_ctx,
7180                                     get_session_info_system(),
7181                                     p->msg_ctx,
7182                                     lp_const_servicename(snum),
7183                                     &pinfo2);
7184         if (!W_ERROR_IS_OK(result)) {
7185                 return result;
7186         }
7187
7188         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7189         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7190                 count, prt_status.status, prt_status.message));
7191
7192         if (count == 0) {
7193                 SAFE_FREE(queue);
7194                 TALLOC_FREE(pinfo2);
7195                 return WERR_OK;
7196         }
7197
7198         switch (r->in.level) {
7199         case 1:
7200                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7201                                          pinfo2, r->out.info, r->out.count);
7202                 break;
7203         case 2:
7204                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7205                                          pinfo2, r->out.info, r->out.count);
7206                 break;
7207         case 3:
7208                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7209                                          pinfo2, r->out.info, r->out.count);
7210                 break;
7211         default:
7212                 result = WERR_UNKNOWN_LEVEL;
7213                 break;
7214         }
7215
7216         SAFE_FREE(queue);
7217         TALLOC_FREE(pinfo2);
7218
7219         if (!W_ERROR_IS_OK(result)) {
7220                 return result;
7221         }
7222
7223         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7224                                                      spoolss_EnumJobs,
7225                                                      *r->out.info, r->in.level,
7226                                                      *r->out.count);
7227         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7228         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7229
7230         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7231 }
7232
7233 /****************************************************************
7234  _spoolss_ScheduleJob
7235 ****************************************************************/
7236
7237 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7238                             struct spoolss_ScheduleJob *r)
7239 {
7240         return WERR_OK;
7241 }
7242
7243 /****************************************************************
7244 ****************************************************************/
7245
7246 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7247                                struct messaging_context *msg_ctx,
7248                                const char *printer_name,
7249                                uint32_t job_id,
7250                                struct spoolss_SetJobInfo1 *r)
7251 {
7252         char *old_doc_name;
7253
7254         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7255                 return WERR_BADFID;
7256         }
7257
7258         if (strequal(old_doc_name, r->document_name)) {
7259                 return WERR_OK;
7260         }
7261
7262         if (!print_job_set_name(server_event_context(), msg_ctx,
7263                                 printer_name, job_id, r->document_name)) {
7264                 return WERR_BADFID;
7265         }
7266
7267         return WERR_OK;
7268 }
7269
7270 /****************************************************************
7271  _spoolss_SetJob
7272 ****************************************************************/
7273
7274 WERROR _spoolss_SetJob(struct pipes_struct *p,
7275                        struct spoolss_SetJob *r)
7276 {
7277         const struct auth_session_info *session_info = p->session_info;
7278         int snum;
7279         WERROR errcode = WERR_BADFUNC;
7280
7281         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7282                 return WERR_BADFID;
7283         }
7284
7285         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7286                 return WERR_INVALID_PRINTER_NAME;
7287         }
7288
7289         switch (r->in.command) {
7290         case SPOOLSS_JOB_CONTROL_CANCEL:
7291         case SPOOLSS_JOB_CONTROL_DELETE:
7292                 errcode = print_job_delete(session_info, p->msg_ctx,
7293                                            snum, r->in.job_id);
7294                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7295                         errcode = WERR_OK;
7296                 }
7297                 break;
7298         case SPOOLSS_JOB_CONTROL_PAUSE:
7299                 if (print_job_pause(session_info, p->msg_ctx,
7300                                     snum, r->in.job_id, &errcode)) {
7301                         errcode = WERR_OK;
7302                 }
7303                 break;
7304         case SPOOLSS_JOB_CONTROL_RESTART:
7305         case SPOOLSS_JOB_CONTROL_RESUME:
7306                 if (print_job_resume(session_info, p->msg_ctx,
7307                                      snum, r->in.job_id, &errcode)) {
7308                         errcode = WERR_OK;
7309                 }
7310                 break;
7311         case 0:
7312                 errcode = WERR_OK;
7313                 break;
7314         default:
7315                 return WERR_UNKNOWN_LEVEL;
7316         }
7317
7318         if (!W_ERROR_IS_OK(errcode)) {
7319                 return errcode;
7320         }
7321
7322         if (r->in.ctr == NULL) {
7323                 return errcode;
7324         }
7325
7326         switch (r->in.ctr->level) {
7327         case 1:
7328                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7329                                            lp_const_servicename(snum),
7330                                            r->in.job_id,
7331                                            r->in.ctr->info.info1);
7332                 break;
7333         case 2:
7334         case 3:
7335         case 4:
7336         default:
7337                 return WERR_UNKNOWN_LEVEL;
7338         }
7339
7340         return errcode;
7341 }
7342
7343 /****************************************************************************
7344  Enumerates all printer drivers by level and architecture.
7345 ****************************************************************************/
7346
7347 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7348                                                        const struct auth_session_info *session_info,
7349                                                        struct messaging_context *msg_ctx,
7350                                                        const char *servername,
7351                                                        const char *architecture,
7352                                                        uint32_t level,
7353                                                        union spoolss_DriverInfo **info_p,
7354                                                        uint32_t *count_p)
7355 {
7356         int i;
7357         uint32_t version;
7358         struct spoolss_DriverInfo8 *driver;
7359         union spoolss_DriverInfo *info = NULL;
7360         uint32_t count = 0;
7361         WERROR result = WERR_OK;
7362         uint32_t num_drivers;
7363         const char **drivers;
7364         struct dcerpc_binding_handle *b;
7365         TALLOC_CTX *tmp_ctx = NULL;
7366
7367         *count_p = 0;
7368         *info_p = NULL;
7369
7370         tmp_ctx = talloc_new(mem_ctx);
7371         if (!tmp_ctx) {
7372                 return WERR_NOMEM;
7373         }
7374
7375         result = winreg_printer_binding_handle(tmp_ctx,
7376                                                session_info,
7377                                                msg_ctx,
7378                                                &b);
7379         if (!W_ERROR_IS_OK(result)) {
7380                 goto out;
7381         }
7382
7383         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7384                 result = winreg_get_driver_list(tmp_ctx, b,
7385                                                 architecture, version,
7386                                                 &num_drivers, &drivers);
7387                 if (!W_ERROR_IS_OK(result)) {
7388                         goto out;
7389                 }
7390                 DEBUG(4, ("we have:[%d] drivers in environment"
7391                           " [%s] and version [%d]\n",
7392                           num_drivers, architecture, version));
7393
7394                 if (num_drivers != 0) {
7395                         info = talloc_realloc(tmp_ctx, info,
7396                                                     union spoolss_DriverInfo,
7397                                                     count + num_drivers);
7398                         if (!info) {
7399                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7400                                         "failed to enlarge driver info buffer!\n"));
7401                                 result = WERR_NOMEM;
7402                                 goto out;
7403                         }
7404                 }
7405
7406                 for (i = 0; i < num_drivers; i++) {
7407                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7408
7409                         result = winreg_get_driver(tmp_ctx, b,
7410                                                    architecture, drivers[i],
7411                                                    version, &driver);
7412                         if (!W_ERROR_IS_OK(result)) {
7413                                 goto out;
7414                         }
7415
7416                         switch (level) {
7417                         case 1:
7418                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7419                                                                    driver, servername);
7420                                 break;
7421                         case 2:
7422                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7423                                                                    driver, servername);
7424                                 break;
7425                         case 3:
7426                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7427                                                                    driver, servername);
7428                                 break;
7429                         case 4:
7430                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7431                                                                    driver, servername);
7432                                 break;
7433                         case 5:
7434                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7435                                                                    driver, servername);
7436                                 break;
7437                         case 6:
7438                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7439                                                                    driver, servername);
7440                                 break;
7441                         case 8:
7442                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7443                                                                    driver, servername);
7444                                 break;
7445                         default:
7446                                 result = WERR_UNKNOWN_LEVEL;
7447                                 break;
7448                         }
7449
7450                         TALLOC_FREE(driver);
7451
7452                         if (!W_ERROR_IS_OK(result)) {
7453                                 goto out;
7454                         }
7455                 }
7456
7457                 count += num_drivers;
7458                 TALLOC_FREE(drivers);
7459         }
7460
7461 out:
7462         if (W_ERROR_IS_OK(result)) {
7463                 *info_p = talloc_move(mem_ctx, &info);
7464                 *count_p = count;
7465         }
7466
7467         talloc_free(tmp_ctx);
7468         return result;
7469 }
7470
7471 /****************************************************************************
7472  Enumerates all printer drivers by level.
7473 ****************************************************************************/
7474
7475 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7476                                        const struct auth_session_info *session_info,
7477                                        struct messaging_context *msg_ctx,
7478                                        const char *servername,
7479                                        const char *architecture,
7480                                        uint32_t level,
7481                                        union spoolss_DriverInfo **info_p,
7482                                        uint32_t *count_p)
7483 {
7484         uint32_t a,i;
7485         WERROR result = WERR_OK;
7486
7487         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7488
7489                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7490
7491                         union spoolss_DriverInfo *info = NULL;
7492                         uint32_t count = 0;
7493
7494                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7495                                                                           session_info,
7496                                                                           msg_ctx,
7497                                                                           servername,
7498                                                                           archi_table[a].long_archi,
7499                                                                           level,
7500                                                                           &info,
7501                                                                           &count);
7502                         if (!W_ERROR_IS_OK(result)) {
7503                                 continue;
7504                         }
7505
7506                         for (i=0; i < count; i++) {
7507                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7508                                              info[i], info_p, count_p);
7509                         }
7510                 }
7511
7512                 return result;
7513         }
7514
7515         return enumprinterdrivers_level_by_architecture(mem_ctx,
7516                                                         session_info,
7517                                                         msg_ctx,
7518                                                         servername,
7519                                                         architecture,
7520                                                         level,
7521                                                         info_p,
7522                                                         count_p);
7523 }
7524
7525 /****************************************************************
7526  _spoolss_EnumPrinterDrivers
7527 ****************************************************************/
7528
7529 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7530                                    struct spoolss_EnumPrinterDrivers *r)
7531 {
7532         const char *cservername;
7533         WERROR result;
7534
7535         /* that's an [in out] buffer */
7536
7537         if (!r->in.buffer && (r->in.offered != 0)) {
7538                 return WERR_INVALID_PARAM;
7539         }
7540
7541         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7542
7543         *r->out.needed = 0;
7544         *r->out.count = 0;
7545         *r->out.info = NULL;
7546
7547         cservername = canon_servername(r->in.server);
7548
7549         if (!is_myname_or_ipaddr(cservername)) {
7550                 return WERR_UNKNOWN_PRINTER_DRIVER;
7551         }
7552
7553         result = enumprinterdrivers_level(p->mem_ctx,
7554                                           get_session_info_system(),
7555                                           p->msg_ctx,
7556                                           cservername,
7557                                           r->in.environment,
7558                                           r->in.level,
7559                                           r->out.info,
7560                                           r->out.count);
7561         if (!W_ERROR_IS_OK(result)) {
7562                 return result;
7563         }
7564
7565         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7566                                                      spoolss_EnumPrinterDrivers,
7567                                                      *r->out.info, r->in.level,
7568                                                      *r->out.count);
7569         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7570         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7571
7572         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7573 }
7574
7575 /****************************************************************
7576  _spoolss_EnumForms
7577 ****************************************************************/
7578
7579 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7580                           struct spoolss_EnumForms *r)
7581 {
7582         WERROR result;
7583
7584         *r->out.count = 0;
7585         *r->out.needed = 0;
7586         *r->out.info = NULL;
7587
7588         /* that's an [in out] buffer */
7589
7590         if (!r->in.buffer && (r->in.offered != 0) ) {
7591                 return WERR_INVALID_PARAM;
7592         }
7593
7594         DEBUG(4,("_spoolss_EnumForms\n"));
7595         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7596         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7597
7598         switch (r->in.level) {
7599         case 1:
7600                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7601                                                    get_session_info_system(),
7602                                                    p->msg_ctx,
7603                                                    r->out.count,
7604                                                    r->out.info);
7605                 break;
7606         default:
7607                 result = WERR_UNKNOWN_LEVEL;
7608                 break;
7609         }
7610
7611         if (!W_ERROR_IS_OK(result)) {
7612                 return result;
7613         }
7614
7615         if (*r->out.count == 0) {
7616                 return WERR_NO_MORE_ITEMS;
7617         }
7618
7619         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7620                                                      spoolss_EnumForms,
7621                                                      *r->out.info, r->in.level,
7622                                                      *r->out.count);
7623         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7624         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7625
7626         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7627 }
7628
7629 /****************************************************************
7630  _spoolss_GetForm
7631 ****************************************************************/
7632
7633 WERROR _spoolss_GetForm(struct pipes_struct *p,
7634                         struct spoolss_GetForm *r)
7635 {
7636         WERROR result;
7637
7638         /* that's an [in out] buffer */
7639
7640         if (!r->in.buffer && (r->in.offered != 0)) {
7641                 return WERR_INVALID_PARAM;
7642         }
7643
7644         DEBUG(4,("_spoolss_GetForm\n"));
7645         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7646         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7647
7648         switch (r->in.level) {
7649         case 1:
7650                 result = winreg_printer_getform1_internal(p->mem_ctx,
7651                                                  get_session_info_system(),
7652                                                  p->msg_ctx,
7653                                                  r->in.form_name,
7654                                                  &r->out.info->info1);
7655                 break;
7656         default:
7657                 result = WERR_UNKNOWN_LEVEL;
7658                 break;
7659         }
7660
7661         if (!W_ERROR_IS_OK(result)) {
7662                 TALLOC_FREE(r->out.info);
7663                 return result;
7664         }
7665
7666         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7667                                                r->out.info, r->in.level);
7668         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7669
7670         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7671 }
7672
7673 /****************************************************************************
7674 ****************************************************************************/
7675
7676 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7677                           struct spoolss_PortInfo1 *r,
7678                           const char *name)
7679 {
7680         r->port_name = talloc_strdup(mem_ctx, name);
7681         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7682
7683         return WERR_OK;
7684 }
7685
7686 /****************************************************************************
7687  TODO: This probably needs distinguish between TCP/IP and Local ports
7688  somehow.
7689 ****************************************************************************/
7690
7691 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7692                           struct spoolss_PortInfo2 *r,
7693                           const char *name)
7694 {
7695         r->port_name = talloc_strdup(mem_ctx, name);
7696         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7697
7698         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7699         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7700
7701         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7702         W_ERROR_HAVE_NO_MEMORY(r->description);
7703
7704         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7705         r->reserved = 0;
7706
7707         return WERR_OK;
7708 }
7709
7710
7711 /****************************************************************************
7712  wrapper around the enumer ports command
7713 ****************************************************************************/
7714
7715 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7716 {
7717         char *cmd = lp_enumports_cmd();
7718         char **qlines = NULL;
7719         char *command = NULL;
7720         int numlines;
7721         int ret;
7722         int fd;
7723
7724         *count = 0;
7725         *lines = NULL;
7726
7727         /* if no hook then just fill in the default port */
7728
7729         if ( !*cmd ) {
7730                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7731                         return WERR_NOMEM;
7732                 }
7733                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7734                         TALLOC_FREE(qlines);
7735                         return WERR_NOMEM;
7736                 }
7737                 qlines[1] = NULL;
7738                 numlines = 1;
7739         }
7740         else {
7741                 /* we have a valid enumport command */
7742
7743                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7744                 if (!command) {
7745                         return WERR_NOMEM;
7746                 }
7747
7748                 DEBUG(10,("Running [%s]\n", command));
7749                 ret = smbrun(command, &fd);
7750                 DEBUG(10,("Returned [%d]\n", ret));
7751                 TALLOC_FREE(command);
7752                 if (ret != 0) {
7753                         if (fd != -1) {
7754                                 close(fd);
7755                         }
7756                         return WERR_ACCESS_DENIED;
7757                 }
7758
7759                 numlines = 0;
7760                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7761                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7762                 close(fd);
7763         }
7764
7765         *count = numlines;
7766         *lines = qlines;
7767
7768         return WERR_OK;
7769 }
7770
7771 /****************************************************************************
7772  enumports level 1.
7773 ****************************************************************************/
7774
7775 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7776                                 union spoolss_PortInfo **info_p,
7777                                 uint32_t *count)
7778 {
7779         union spoolss_PortInfo *info = NULL;
7780         int i=0;
7781         WERROR result = WERR_OK;
7782         char **qlines = NULL;
7783         int numlines = 0;
7784
7785         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7786         if (!W_ERROR_IS_OK(result)) {
7787                 goto out;
7788         }
7789
7790         if (numlines) {
7791                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7792                 if (!info) {
7793                         DEBUG(10,("Returning WERR_NOMEM\n"));
7794                         result = WERR_NOMEM;
7795                         goto out;
7796                 }
7797
7798                 for (i=0; i<numlines; i++) {
7799                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7800                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7801                         if (!W_ERROR_IS_OK(result)) {
7802                                 goto out;
7803                         }
7804                 }
7805         }
7806         TALLOC_FREE(qlines);
7807
7808 out:
7809         if (!W_ERROR_IS_OK(result)) {
7810                 TALLOC_FREE(info);
7811                 TALLOC_FREE(qlines);
7812                 *count = 0;
7813                 *info_p = NULL;
7814                 return result;
7815         }
7816
7817         *info_p = info;
7818         *count = numlines;
7819
7820         return WERR_OK;
7821 }
7822
7823 /****************************************************************************
7824  enumports level 2.
7825 ****************************************************************************/
7826
7827 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7828                                 union spoolss_PortInfo **info_p,
7829                                 uint32_t *count)
7830 {
7831         union spoolss_PortInfo *info = NULL;
7832         int i=0;
7833         WERROR result = WERR_OK;
7834         char **qlines = NULL;
7835         int numlines = 0;
7836
7837         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7838         if (!W_ERROR_IS_OK(result)) {
7839                 goto out;
7840         }
7841
7842         if (numlines) {
7843                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7844                 if (!info) {
7845                         DEBUG(10,("Returning WERR_NOMEM\n"));
7846                         result = WERR_NOMEM;
7847                         goto out;
7848                 }
7849
7850                 for (i=0; i<numlines; i++) {
7851                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7852                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7853                         if (!W_ERROR_IS_OK(result)) {
7854                                 goto out;
7855                         }
7856                 }
7857         }
7858         TALLOC_FREE(qlines);
7859
7860 out:
7861         if (!W_ERROR_IS_OK(result)) {
7862                 TALLOC_FREE(info);
7863                 TALLOC_FREE(qlines);
7864                 *count = 0;
7865                 *info_p = NULL;
7866                 return result;
7867         }
7868
7869         *info_p = info;
7870         *count = numlines;
7871
7872         return WERR_OK;
7873 }
7874
7875 /****************************************************************
7876  _spoolss_EnumPorts
7877 ****************************************************************/
7878
7879 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7880                           struct spoolss_EnumPorts *r)
7881 {
7882         WERROR result;
7883
7884         /* that's an [in out] buffer */
7885
7886         if (!r->in.buffer && (r->in.offered != 0)) {
7887                 return WERR_INVALID_PARAM;
7888         }
7889
7890         DEBUG(4,("_spoolss_EnumPorts\n"));
7891
7892         *r->out.count = 0;
7893         *r->out.needed = 0;
7894         *r->out.info = NULL;
7895
7896         switch (r->in.level) {
7897         case 1:
7898                 result = enumports_level_1(p->mem_ctx, r->out.info,
7899                                            r->out.count);
7900                 break;
7901         case 2:
7902                 result = enumports_level_2(p->mem_ctx, r->out.info,
7903                                            r->out.count);
7904                 break;
7905         default:
7906                 return WERR_UNKNOWN_LEVEL;
7907         }
7908
7909         if (!W_ERROR_IS_OK(result)) {
7910                 return result;
7911         }
7912
7913         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7914                                                      spoolss_EnumPorts,
7915                                                      *r->out.info, r->in.level,
7916                                                      *r->out.count);
7917         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7918         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7919
7920         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7921 }
7922
7923 /****************************************************************************
7924 ****************************************************************************/
7925
7926 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7927                                            const char *server,
7928                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7929                                            struct spoolss_DeviceMode *devmode,
7930                                            struct security_descriptor *secdesc,
7931                                            struct spoolss_UserLevelCtr *user_ctr,
7932                                            struct policy_handle *handle)
7933 {
7934         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7935         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7936         int     snum;
7937         WERROR err = WERR_OK;
7938
7939         /* samba does not have a concept of local, non-shared printers yet, so
7940          * make sure we always setup sharename - gd */
7941         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7942             (info2->printername != NULL && info2->printername[0] != '\0')) {
7943                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7944                         "no sharename has been set, setting printername %s as sharename\n",
7945                         info2->printername));
7946                 info2->sharename = info2->printername;
7947         }
7948
7949         /* check to see if the printer already exists */
7950         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7951                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7952                         info2->sharename));
7953                 return WERR_PRINTER_ALREADY_EXISTS;
7954         }
7955
7956         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7957                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7958                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7959                                 info2->printername));
7960                         return WERR_PRINTER_ALREADY_EXISTS;
7961                 }
7962         }
7963
7964         /* validate printer info struct */
7965         if (!info2->printername || strlen(info2->printername) == 0) {
7966                 return WERR_INVALID_PRINTER_NAME;
7967         }
7968         if (!info2->portname || strlen(info2->portname) == 0) {
7969                 return WERR_UNKNOWN_PORT;
7970         }
7971         if (!info2->drivername || strlen(info2->drivername) == 0) {
7972                 return WERR_UNKNOWN_PRINTER_DRIVER;
7973         }
7974         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7975                 return WERR_UNKNOWN_PRINTPROCESSOR;
7976         }
7977
7978         /* FIXME!!!  smbd should check to see if the driver is installed before
7979            trying to add a printer like this  --jerry */
7980
7981         if (*lp_addprinter_cmd() ) {
7982                 char *raddr;
7983
7984                 raddr = tsocket_address_inet_addr_string(p->remote_address,
7985                                                          p->mem_ctx);
7986                 if (raddr == NULL) {
7987                         return WERR_NOMEM;
7988                 }
7989
7990                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7991                                        info2, raddr,
7992                                        p->msg_ctx) ) {
7993                         return WERR_ACCESS_DENIED;
7994                 }
7995         } else {
7996                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7997                         "smb.conf parameter \"addprinter command\" is defined. This "
7998                         "parameter must exist for this call to succeed\n",
7999                         info2->sharename ));
8000         }
8001
8002         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8003                 return WERR_ACCESS_DENIED;
8004         }
8005
8006         /* you must be a printer admin to add a new printer */
8007         if (!print_access_check(p->session_info,
8008                                 p->msg_ctx,
8009                                 snum,
8010                                 PRINTER_ACCESS_ADMINISTER)) {
8011                 return WERR_ACCESS_DENIED;
8012         }
8013
8014         /*
8015          * Do sanity check on the requested changes for Samba.
8016          */
8017
8018         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8019                 return WERR_INVALID_PARAM;
8020         }
8021
8022         if (devmode == NULL) {
8023                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8024         }
8025
8026         update_dsspooler(p->mem_ctx,
8027                          get_session_info_system(),
8028                          p->msg_ctx,
8029                          0,
8030                          info2,
8031                          NULL);
8032
8033         err = winreg_update_printer_internal(p->mem_ctx,
8034                                     get_session_info_system(),
8035                                     p->msg_ctx,
8036                                     info2->sharename,
8037                                     info2_mask,
8038                                     info2,
8039                                     devmode,
8040                                     secdesc);
8041         if (!W_ERROR_IS_OK(err)) {
8042                 return err;
8043         }
8044
8045         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8046         if (!W_ERROR_IS_OK(err)) {
8047                 /* Handle open failed - remove addition. */
8048                 ZERO_STRUCTP(handle);
8049                 return err;
8050         }
8051
8052         return WERR_OK;
8053 }
8054
8055 /****************************************************************
8056  _spoolss_AddPrinterEx
8057 ****************************************************************/
8058
8059 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8060                              struct spoolss_AddPrinterEx *r)
8061 {
8062         switch (r->in.info_ctr->level) {
8063         case 1:
8064                 /* we don't handle yet */
8065                 /* but I know what to do ... */
8066                 return WERR_UNKNOWN_LEVEL;
8067         case 2:
8068                 return spoolss_addprinterex_level_2(p, r->in.server,
8069                                                     r->in.info_ctr,
8070                                                     r->in.devmode_ctr->devmode,
8071                                                     r->in.secdesc_ctr->sd,
8072                                                     r->in.userlevel_ctr,
8073                                                     r->out.handle);
8074         default:
8075                 return WERR_UNKNOWN_LEVEL;
8076         }
8077 }
8078
8079 /****************************************************************
8080  _spoolss_AddPrinter
8081 ****************************************************************/
8082
8083 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8084                            struct spoolss_AddPrinter *r)
8085 {
8086         struct spoolss_AddPrinterEx a;
8087         struct spoolss_UserLevelCtr userlevel_ctr;
8088
8089         ZERO_STRUCT(userlevel_ctr);
8090
8091         userlevel_ctr.level = 1;
8092
8093         a.in.server             = r->in.server;
8094         a.in.info_ctr           = r->in.info_ctr;
8095         a.in.devmode_ctr        = r->in.devmode_ctr;
8096         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8097         a.in.userlevel_ctr      = &userlevel_ctr;
8098         a.out.handle            = r->out.handle;
8099
8100         return _spoolss_AddPrinterEx(p, &a);
8101 }
8102
8103 /****************************************************************
8104  _spoolss_AddPrinterDriverEx
8105 ****************************************************************/
8106
8107 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8108                                    struct spoolss_AddPrinterDriverEx *r)
8109 {
8110         WERROR err = WERR_OK;
8111         const char *driver_name = NULL;
8112         uint32_t version;
8113         const char *fn;
8114
8115         switch (p->opnum) {
8116                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8117                         fn = "_spoolss_AddPrinterDriver";
8118                         break;
8119                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8120                         fn = "_spoolss_AddPrinterDriverEx";
8121                         break;
8122                 default:
8123                         return WERR_INVALID_PARAM;
8124         }
8125
8126         /*
8127          * we only support the semantics of AddPrinterDriver()
8128          * i.e. only copy files that are newer than existing ones
8129          */
8130
8131         if (r->in.flags == 0) {
8132                 return WERR_INVALID_PARAM;
8133         }
8134
8135         if (r->in.flags != APD_COPY_NEW_FILES) {
8136                 return WERR_ACCESS_DENIED;
8137         }
8138
8139         /* FIXME */
8140         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8141                 /* Clever hack from Martin Zielinski <mz@seh.de>
8142                  * to allow downgrade from level 8 (Vista).
8143                  */
8144                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8145                         r->in.info_ctr->level));
8146                 return WERR_UNKNOWN_LEVEL;
8147         }
8148
8149         DEBUG(5,("Cleaning driver's information\n"));
8150         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8151         if (!W_ERROR_IS_OK(err))
8152                 goto done;
8153
8154         DEBUG(5,("Moving driver to final destination\n"));
8155         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8156         if (!W_ERROR_IS_OK(err)) {
8157                 goto done;
8158         }
8159
8160         err = winreg_add_driver_internal(p->mem_ctx,
8161                                 get_session_info_system(),
8162                                 p->msg_ctx,
8163                                 r->in.info_ctr,
8164                                 &driver_name,
8165                                 &version);
8166         if (!W_ERROR_IS_OK(err)) {
8167                 goto done;
8168         }
8169
8170         /*
8171          * I think this is where he DrvUpgradePrinter() hook would be
8172          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8173          * server.  Right now, we just need to send ourselves a message
8174          * to update each printer bound to this driver.   --jerry
8175          */
8176
8177         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8178                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8179                         fn, driver_name));
8180         }
8181
8182 done:
8183         return err;
8184 }
8185
8186 /****************************************************************
8187  _spoolss_AddPrinterDriver
8188 ****************************************************************/
8189
8190 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8191                                  struct spoolss_AddPrinterDriver *r)
8192 {
8193         struct spoolss_AddPrinterDriverEx a;
8194
8195         switch (r->in.info_ctr->level) {
8196         case 2:
8197         case 3:
8198         case 4:
8199         case 5:
8200                 break;
8201         default:
8202                 return WERR_UNKNOWN_LEVEL;
8203         }
8204
8205         a.in.servername         = r->in.servername;
8206         a.in.info_ctr           = r->in.info_ctr;
8207         a.in.flags              = APD_COPY_NEW_FILES;
8208
8209         return _spoolss_AddPrinterDriverEx(p, &a);
8210 }
8211
8212 /****************************************************************************
8213 ****************************************************************************/
8214
8215 struct _spoolss_paths {
8216         int type;
8217         const char *share;
8218         const char *dir;
8219 };
8220
8221 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8222
8223 static const struct _spoolss_paths spoolss_paths[]= {
8224         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8225         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8226 };
8227
8228 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8229                                           const char *servername,
8230                                           const char *environment,
8231                                           int component,
8232                                           char **path)
8233 {
8234         const char *pservername = NULL;
8235         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8236         const char *short_archi;
8237
8238         *path = NULL;
8239
8240         /* environment may be empty */
8241         if (environment && strlen(environment)) {
8242                 long_archi = environment;
8243         }
8244
8245         /* servername may be empty */
8246         if (servername && strlen(servername)) {
8247                 pservername = canon_servername(servername);
8248
8249                 if (!is_myname_or_ipaddr(pservername)) {
8250                         return WERR_INVALID_PARAM;
8251                 }
8252         }
8253
8254         if (!(short_archi = get_short_archi(long_archi))) {
8255                 return WERR_INVALID_ENVIRONMENT;
8256         }
8257
8258         switch (component) {
8259         case SPOOLSS_PRTPROCS_PATH:
8260         case SPOOLSS_DRIVER_PATH:
8261                 if (pservername) {
8262                         *path = talloc_asprintf(mem_ctx,
8263                                         "\\\\%s\\%s\\%s",
8264                                         pservername,
8265                                         spoolss_paths[component].share,
8266                                         short_archi);
8267                 } else {
8268                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8269                                         SPOOLSS_DEFAULT_SERVER_PATH,
8270                                         spoolss_paths[component].dir,
8271                                         short_archi);
8272                 }
8273                 break;
8274         default:
8275                 return WERR_INVALID_PARAM;
8276         }
8277
8278         if (!*path) {
8279                 return WERR_NOMEM;
8280         }
8281
8282         return WERR_OK;
8283 }
8284
8285 /****************************************************************************
8286 ****************************************************************************/
8287
8288 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8289                                           const char *servername,
8290                                           const char *environment,
8291                                           struct spoolss_DriverDirectoryInfo1 *r)
8292 {
8293         WERROR werr;
8294         char *path = NULL;
8295
8296         werr = compose_spoolss_server_path(mem_ctx,
8297                                            servername,
8298                                            environment,
8299                                            SPOOLSS_DRIVER_PATH,
8300                                            &path);
8301         if (!W_ERROR_IS_OK(werr)) {
8302                 return werr;
8303         }
8304
8305         DEBUG(4,("printer driver directory: [%s]\n", path));
8306
8307         r->directory_name = path;
8308
8309         return WERR_OK;
8310 }
8311
8312 /****************************************************************
8313  _spoolss_GetPrinterDriverDirectory
8314 ****************************************************************/
8315
8316 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8317                                           struct spoolss_GetPrinterDriverDirectory *r)
8318 {
8319         WERROR werror;
8320
8321         /* that's an [in out] buffer */
8322
8323         if (!r->in.buffer && (r->in.offered != 0)) {
8324                 return WERR_INVALID_PARAM;
8325         }
8326
8327         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8328                 r->in.level));
8329
8330         *r->out.needed = 0;
8331
8332         /* r->in.level is ignored */
8333
8334         werror = getprinterdriverdir_level_1(p->mem_ctx,
8335                                              r->in.server,
8336                                              r->in.environment,
8337                                              &r->out.info->info1);
8338         if (!W_ERROR_IS_OK(werror)) {
8339                 TALLOC_FREE(r->out.info);
8340                 return werror;
8341         }
8342
8343         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8344                                                r->out.info, r->in.level);
8345         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8346
8347         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8348 }
8349
8350 /****************************************************************
8351  _spoolss_EnumPrinterData
8352 ****************************************************************/
8353
8354 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8355                                 struct spoolss_EnumPrinterData *r)
8356 {
8357         WERROR result;
8358         struct spoolss_EnumPrinterDataEx r2;
8359         uint32_t count;
8360         struct spoolss_PrinterEnumValues *info, *val = NULL;
8361         uint32_t needed;
8362
8363         r2.in.handle    = r->in.handle;
8364         r2.in.key_name  = "PrinterDriverData";
8365         r2.in.offered   = 0;
8366         r2.out.count    = &count;
8367         r2.out.info     = &info;
8368         r2.out.needed   = &needed;
8369
8370         result = _spoolss_EnumPrinterDataEx(p, &r2);
8371         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8372                 r2.in.offered = needed;
8373                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8374         }
8375         if (!W_ERROR_IS_OK(result)) {
8376                 return result;
8377         }
8378
8379         /*
8380          * The NT machine wants to know the biggest size of value and data
8381          *
8382          * cf: MSDN EnumPrinterData remark section
8383          */
8384
8385         if (!r->in.value_offered && !r->in.data_offered) {
8386                 uint32_t biggest_valuesize = 0;
8387                 uint32_t biggest_datasize = 0;
8388                 int i, name_length;
8389
8390                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8391
8392                 for (i=0; i<count; i++) {
8393
8394                         name_length = strlen(info[i].value_name);
8395                         if (strlen(info[i].value_name) > biggest_valuesize) {
8396                                 biggest_valuesize = name_length;
8397                         }
8398
8399                         if (info[i].data_length > biggest_datasize) {
8400                                 biggest_datasize = info[i].data_length;
8401                         }
8402
8403                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8404                                 biggest_datasize));
8405                 }
8406
8407                 /* the value is an UNICODE string but real_value_size is the length
8408                    in bytes including the trailing 0 */
8409
8410                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8411                 *r->out.data_needed  = biggest_datasize;
8412
8413                 DEBUG(6,("final values: [%d], [%d]\n",
8414                         *r->out.value_needed, *r->out.data_needed));
8415
8416                 return WERR_OK;
8417         }
8418
8419         if (r->in.enum_index < count) {
8420                 val = &info[r->in.enum_index];
8421         }
8422
8423         if (val == NULL) {
8424                 /* out_value should default to "" or else NT4 has
8425                    problems unmarshalling the response */
8426
8427                 if (r->in.value_offered) {
8428                         *r->out.value_needed = 1;
8429                         r->out.value_name = talloc_strdup(r, "");
8430                         if (!r->out.value_name) {
8431                                 return WERR_NOMEM;
8432                         }
8433                 } else {
8434                         r->out.value_name = NULL;
8435                         *r->out.value_needed = 0;
8436                 }
8437
8438                 /* the data is counted in bytes */
8439
8440                 *r->out.data_needed = r->in.data_offered;
8441
8442                 result = WERR_NO_MORE_ITEMS;
8443         } else {
8444                 /*
8445                  * the value is:
8446                  * - counted in bytes in the request
8447                  * - counted in UNICODE chars in the max reply
8448                  * - counted in bytes in the real size
8449                  *
8450                  * take a pause *before* coding not *during* coding
8451                  */
8452
8453                 /* name */
8454                 if (r->in.value_offered) {
8455                         r->out.value_name = talloc_strdup(r, val->value_name);
8456                         if (!r->out.value_name) {
8457                                 return WERR_NOMEM;
8458                         }
8459                         *r->out.value_needed = val->value_name_len;
8460                 } else {
8461                         r->out.value_name = NULL;
8462                         *r->out.value_needed = 0;
8463                 }
8464
8465                 /* type */
8466
8467                 *r->out.type = val->type;
8468
8469                 /* data - counted in bytes */
8470
8471                 /*
8472                  * See the section "Dynamically Typed Query Parameters"
8473                  * in MS-RPRN.
8474                  */
8475
8476                 if (r->out.data && val->data && val->data->data &&
8477                                 val->data_length && r->in.data_offered) {
8478                         memcpy(r->out.data, val->data->data,
8479                                 MIN(val->data_length,r->in.data_offered));
8480                 }
8481
8482                 *r->out.data_needed = val->data_length;
8483
8484                 result = WERR_OK;
8485         }
8486
8487         return result;
8488 }
8489
8490 /****************************************************************
8491  _spoolss_SetPrinterData
8492 ****************************************************************/
8493
8494 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8495                                struct spoolss_SetPrinterData *r)
8496 {
8497         struct spoolss_SetPrinterDataEx r2;
8498
8499         r2.in.handle            = r->in.handle;
8500         r2.in.key_name          = "PrinterDriverData";
8501         r2.in.value_name        = r->in.value_name;
8502         r2.in.type              = r->in.type;
8503         r2.in.data              = r->in.data;
8504         r2.in.offered           = r->in.offered;
8505
8506         return _spoolss_SetPrinterDataEx(p, &r2);
8507 }
8508
8509 /****************************************************************
8510  _spoolss_ResetPrinter
8511 ****************************************************************/
8512
8513 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8514                              struct spoolss_ResetPrinter *r)
8515 {
8516         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8517         int             snum;
8518
8519         DEBUG(5,("_spoolss_ResetPrinter\n"));
8520
8521         /*
8522          * All we do is to check to see if the handle and queue is valid.
8523          * This call really doesn't mean anything to us because we only
8524          * support RAW printing.   --jerry
8525          */
8526
8527         if (!Printer) {
8528                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8529                         OUR_HANDLE(r->in.handle)));
8530                 return WERR_BADFID;
8531         }
8532
8533         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8534                 return WERR_BADFID;
8535
8536
8537         /* blindly return success */
8538         return WERR_OK;
8539 }
8540
8541 /****************************************************************
8542  _spoolss_DeletePrinterData
8543 ****************************************************************/
8544
8545 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8546                                   struct spoolss_DeletePrinterData *r)
8547 {
8548         struct spoolss_DeletePrinterDataEx r2;
8549
8550         r2.in.handle            = r->in.handle;
8551         r2.in.key_name          = "PrinterDriverData";
8552         r2.in.value_name        = r->in.value_name;
8553
8554         return _spoolss_DeletePrinterDataEx(p, &r2);
8555 }
8556
8557 /****************************************************************
8558  _spoolss_AddForm
8559 ****************************************************************/
8560
8561 WERROR _spoolss_AddForm(struct pipes_struct *p,
8562                         struct spoolss_AddForm *r)
8563 {
8564         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8565         int snum = -1;
8566         WERROR status = WERR_OK;
8567         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8568         struct dcerpc_binding_handle *b;
8569         TALLOC_CTX *tmp_ctx = NULL;
8570
8571         DEBUG(5,("_spoolss_AddForm\n"));
8572
8573         if (!Printer) {
8574                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8575                         OUR_HANDLE(r->in.handle)));
8576                 return WERR_BADFID;
8577         }
8578
8579         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8580            and not a printer admin, then fail */
8581
8582         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8583             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8584             !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8585                                           p->session_info->info->domain_name,
8586                                           NULL,
8587                                           p->session_info->security_token,
8588                                           lp_printer_admin(snum))) {
8589                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8590                 return WERR_ACCESS_DENIED;
8591         }
8592
8593         switch (form->flags) {
8594         case SPOOLSS_FORM_USER:
8595         case SPOOLSS_FORM_BUILTIN:
8596         case SPOOLSS_FORM_PRINTER:
8597                 break;
8598         default:
8599                 return WERR_INVALID_PARAM;
8600         }
8601
8602         tmp_ctx = talloc_new(p->mem_ctx);
8603         if (!tmp_ctx) {
8604                 return WERR_NOMEM;
8605         }
8606
8607         status = winreg_printer_binding_handle(tmp_ctx,
8608                                                get_session_info_system(),
8609                                                p->msg_ctx,
8610                                                &b);
8611         if (!W_ERROR_IS_OK(status)) {
8612                 goto done;
8613         }
8614
8615         status = winreg_printer_addform1(tmp_ctx, b, form);
8616         if (!W_ERROR_IS_OK(status)) {
8617                 goto done;
8618         }
8619
8620         /*
8621          * ChangeID must always be set if this is a printer
8622          */
8623         if (Printer->printer_type == SPLHND_PRINTER) {
8624                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8625                         status = WERR_BADFID;
8626                         goto done;
8627                 }
8628
8629                 status = winreg_printer_update_changeid(tmp_ctx, b,
8630                                                         lp_const_servicename(snum));
8631         }
8632
8633 done:
8634         talloc_free(tmp_ctx);
8635         return status;
8636 }
8637
8638 /****************************************************************
8639  _spoolss_DeleteForm
8640 ****************************************************************/
8641
8642 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8643                            struct spoolss_DeleteForm *r)
8644 {
8645         const char *form_name = r->in.form_name;
8646         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8647         int snum = -1;
8648         WERROR status = WERR_OK;
8649         struct dcerpc_binding_handle *b;
8650         TALLOC_CTX *tmp_ctx = NULL;
8651
8652         DEBUG(5,("_spoolss_DeleteForm\n"));
8653
8654         if (!Printer) {
8655                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8656                         OUR_HANDLE(r->in.handle)));
8657                 return WERR_BADFID;
8658         }
8659
8660         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8661             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8662             !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8663                                           p->session_info->info->domain_name,
8664                                           NULL,
8665                                           p->session_info->security_token,
8666                                           lp_printer_admin(snum))) {
8667                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8668                 return WERR_ACCESS_DENIED;
8669         }
8670
8671         tmp_ctx = talloc_new(p->mem_ctx);
8672         if (!tmp_ctx) {
8673                 return WERR_NOMEM;
8674         }
8675
8676         status = winreg_printer_binding_handle(tmp_ctx,
8677                                                get_session_info_system(),
8678                                                p->msg_ctx,
8679                                                &b);
8680         if (!W_ERROR_IS_OK(status)) {
8681                 goto done;
8682         }
8683
8684         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8685         if (!W_ERROR_IS_OK(status)) {
8686                 goto done;
8687         }
8688
8689         /*
8690          * ChangeID must always be set if this is a printer
8691          */
8692         if (Printer->printer_type == SPLHND_PRINTER) {
8693                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8694                         status = WERR_BADFID;
8695                         goto done;
8696                 }
8697
8698                 status = winreg_printer_update_changeid(tmp_ctx, b,
8699                                                         lp_const_servicename(snum));
8700         }
8701
8702 done:
8703         talloc_free(tmp_ctx);
8704         return status;
8705 }
8706
8707 /****************************************************************
8708  _spoolss_SetForm
8709 ****************************************************************/
8710
8711 WERROR _spoolss_SetForm(struct pipes_struct *p,
8712                         struct spoolss_SetForm *r)
8713 {
8714         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8715         const char *form_name = r->in.form_name;
8716         int snum = -1;
8717         WERROR status = WERR_OK;
8718         struct dcerpc_binding_handle *b;
8719         TALLOC_CTX *tmp_ctx = NULL;
8720
8721         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8722
8723         DEBUG(5,("_spoolss_SetForm\n"));
8724
8725         if (!Printer) {
8726                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8727                         OUR_HANDLE(r->in.handle)));
8728                 return WERR_BADFID;
8729         }
8730
8731         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8732            and not a printer admin, then fail */
8733
8734         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8735              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8736              !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8737                                           p->session_info->info->domain_name,
8738                                           NULL,
8739                                           p->session_info->security_token,
8740                                           lp_printer_admin(snum))) {
8741                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8742                 return WERR_ACCESS_DENIED;
8743         }
8744
8745         tmp_ctx = talloc_new(p->mem_ctx);
8746         if (!tmp_ctx) {
8747                 return WERR_NOMEM;
8748         }
8749
8750         status = winreg_printer_binding_handle(tmp_ctx,
8751                                                get_session_info_system(),
8752                                                p->msg_ctx,
8753                                                &b);
8754         if (!W_ERROR_IS_OK(status)) {
8755                 goto done;
8756         }
8757
8758         status = winreg_printer_setform1(tmp_ctx, b,
8759                                          form_name,
8760                                          form);
8761         if (!W_ERROR_IS_OK(status)) {
8762                 goto done;
8763         }
8764
8765         /*
8766          * ChangeID must always be set if this is a printer
8767          */
8768         if (Printer->printer_type == SPLHND_PRINTER) {
8769                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8770                         status = WERR_BADFID;
8771                         goto done;
8772                 }
8773
8774                 status = winreg_printer_update_changeid(tmp_ctx, b,
8775                                                         lp_const_servicename(snum));
8776         }
8777
8778 done:
8779         talloc_free(tmp_ctx);
8780         return status;
8781 }
8782
8783 /****************************************************************************
8784  fill_print_processor1
8785 ****************************************************************************/
8786
8787 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8788                                     struct spoolss_PrintProcessorInfo1 *r,
8789                                     const char *print_processor_name)
8790 {
8791         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8792         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8793
8794         return WERR_OK;
8795 }
8796
8797 /****************************************************************************
8798  enumprintprocessors level 1.
8799 ****************************************************************************/
8800
8801 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8802                                           union spoolss_PrintProcessorInfo **info_p,
8803                                           uint32_t *count)
8804 {
8805         union spoolss_PrintProcessorInfo *info;
8806         WERROR result;
8807
8808         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8809         W_ERROR_HAVE_NO_MEMORY(info);
8810
8811         *count = 1;
8812
8813         result = fill_print_processor1(info, &info[0].info1, "winprint");
8814         if (!W_ERROR_IS_OK(result)) {
8815                 goto out;
8816         }
8817
8818  out:
8819         if (!W_ERROR_IS_OK(result)) {
8820                 TALLOC_FREE(info);
8821                 *count = 0;
8822                 return result;
8823         }
8824
8825         *info_p = info;
8826
8827         return WERR_OK;
8828 }
8829
8830 /****************************************************************
8831  _spoolss_EnumPrintProcessors
8832 ****************************************************************/
8833
8834 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8835                                     struct spoolss_EnumPrintProcessors *r)
8836 {
8837         WERROR result;
8838
8839         /* that's an [in out] buffer */
8840
8841         if (!r->in.buffer && (r->in.offered != 0)) {
8842                 return WERR_INVALID_PARAM;
8843         }
8844
8845         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8846
8847         /*
8848          * Enumerate the print processors ...
8849          *
8850          * Just reply with "winprint", to keep NT happy
8851          * and I can use my nice printer checker.
8852          */
8853
8854         *r->out.count = 0;
8855         *r->out.needed = 0;
8856         *r->out.info = NULL;
8857
8858         if (!get_short_archi(r->in.environment)) {
8859                 return WERR_INVALID_ENVIRONMENT;
8860         }
8861
8862         switch (r->in.level) {
8863         case 1:
8864                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8865                                                      r->out.count);
8866                 break;
8867         default:
8868                 return WERR_UNKNOWN_LEVEL;
8869         }
8870
8871         if (!W_ERROR_IS_OK(result)) {
8872                 return result;
8873         }
8874
8875         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8876                                                      spoolss_EnumPrintProcessors,
8877                                                      *r->out.info, r->in.level,
8878                                                      *r->out.count);
8879         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8880         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8881
8882         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8883 }
8884
8885 /****************************************************************************
8886  fill_printprocdatatype1
8887 ****************************************************************************/
8888
8889 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8890                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8891                                       const char *name_array)
8892 {
8893         r->name_array = talloc_strdup(mem_ctx, name_array);
8894         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8895
8896         return WERR_OK;
8897 }
8898
8899 /****************************************************************************
8900  enumprintprocdatatypes level 1.
8901 ****************************************************************************/
8902
8903 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8904                                              union spoolss_PrintProcDataTypesInfo **info_p,
8905                                              uint32_t *count)
8906 {
8907         WERROR result;
8908         union spoolss_PrintProcDataTypesInfo *info;
8909
8910         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8911         W_ERROR_HAVE_NO_MEMORY(info);
8912
8913         *count = 1;
8914
8915         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8916         if (!W_ERROR_IS_OK(result)) {
8917                 goto out;
8918         }
8919
8920  out:
8921         if (!W_ERROR_IS_OK(result)) {
8922                 TALLOC_FREE(info);
8923                 *count = 0;
8924                 return result;
8925         }
8926
8927         *info_p = info;
8928
8929         return WERR_OK;
8930 }
8931
8932 /****************************************************************
8933  _spoolss_EnumPrintProcDataTypes
8934 ****************************************************************/
8935
8936 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8937                                        struct spoolss_EnumPrintProcDataTypes *r)
8938 {
8939         WERROR result;
8940
8941         /* that's an [in out] buffer */
8942
8943         if (!r->in.buffer && (r->in.offered != 0)) {
8944                 return WERR_INVALID_PARAM;
8945         }
8946
8947         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8948
8949         *r->out.count = 0;
8950         *r->out.needed = 0;
8951         *r->out.info = NULL;
8952
8953         if (r->in.print_processor_name == NULL ||
8954             !strequal(r->in.print_processor_name, "winprint")) {
8955                 return WERR_UNKNOWN_PRINTPROCESSOR;
8956         }
8957
8958         switch (r->in.level) {
8959         case 1:
8960                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8961                                                         r->out.count);
8962                 break;
8963         default:
8964                 return WERR_UNKNOWN_LEVEL;
8965         }
8966
8967         if (!W_ERROR_IS_OK(result)) {
8968                 return result;
8969         }
8970
8971         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8972                                                      spoolss_EnumPrintProcDataTypes,
8973                                                      *r->out.info, r->in.level,
8974                                                      *r->out.count);
8975         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8976         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8977
8978         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8979 }
8980
8981 /****************************************************************************
8982  fill_monitor_1
8983 ****************************************************************************/
8984
8985 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8986                              struct spoolss_MonitorInfo1 *r,
8987                              const char *monitor_name)
8988 {
8989         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8990         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8991
8992         return WERR_OK;
8993 }
8994
8995 /****************************************************************************
8996  fill_monitor_2
8997 ****************************************************************************/
8998
8999 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9000                              struct spoolss_MonitorInfo2 *r,
9001                              const char *monitor_name,
9002                              const char *environment,
9003                              const char *dll_name)
9004 {
9005         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9006         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9007         r->environment                  = talloc_strdup(mem_ctx, environment);
9008         W_ERROR_HAVE_NO_MEMORY(r->environment);
9009         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9010         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9011
9012         return WERR_OK;
9013 }
9014
9015 /****************************************************************************
9016  enumprintmonitors level 1.
9017 ****************************************************************************/
9018
9019 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9020                                         union spoolss_MonitorInfo **info_p,
9021                                         uint32_t *count)
9022 {
9023         union spoolss_MonitorInfo *info;
9024         WERROR result = WERR_OK;
9025
9026         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9027         W_ERROR_HAVE_NO_MEMORY(info);
9028
9029         *count = 2;
9030
9031         result = fill_monitor_1(info, &info[0].info1,
9032                                 SPL_LOCAL_PORT);
9033         if (!W_ERROR_IS_OK(result)) {
9034                 goto out;
9035         }
9036
9037         result = fill_monitor_1(info, &info[1].info1,
9038                                 SPL_TCPIP_PORT);
9039         if (!W_ERROR_IS_OK(result)) {
9040                 goto out;
9041         }
9042
9043 out:
9044         if (!W_ERROR_IS_OK(result)) {
9045                 TALLOC_FREE(info);
9046                 *count = 0;
9047                 return result;
9048         }
9049
9050         *info_p = info;
9051
9052         return WERR_OK;
9053 }
9054
9055 /****************************************************************************
9056  enumprintmonitors level 2.
9057 ****************************************************************************/
9058
9059 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9060                                         union spoolss_MonitorInfo **info_p,
9061                                         uint32_t *count)
9062 {
9063         union spoolss_MonitorInfo *info;
9064         WERROR result = WERR_OK;
9065
9066         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9067         W_ERROR_HAVE_NO_MEMORY(info);
9068
9069         *count = 2;
9070
9071         result = fill_monitor_2(info, &info[0].info2,
9072                                 SPL_LOCAL_PORT,
9073                                 "Windows NT X86", /* FIXME */
9074                                 "localmon.dll");
9075         if (!W_ERROR_IS_OK(result)) {
9076                 goto out;
9077         }
9078
9079         result = fill_monitor_2(info, &info[1].info2,
9080                                 SPL_TCPIP_PORT,
9081                                 "Windows NT X86", /* FIXME */
9082                                 "tcpmon.dll");
9083         if (!W_ERROR_IS_OK(result)) {
9084                 goto out;
9085         }
9086
9087 out:
9088         if (!W_ERROR_IS_OK(result)) {
9089                 TALLOC_FREE(info);
9090                 *count = 0;
9091                 return result;
9092         }
9093
9094         *info_p = info;
9095
9096         return WERR_OK;
9097 }
9098
9099 /****************************************************************
9100  _spoolss_EnumMonitors
9101 ****************************************************************/
9102
9103 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9104                              struct spoolss_EnumMonitors *r)
9105 {
9106         WERROR result;
9107
9108         /* that's an [in out] buffer */
9109
9110         if (!r->in.buffer && (r->in.offered != 0)) {
9111                 return WERR_INVALID_PARAM;
9112         }
9113
9114         DEBUG(5,("_spoolss_EnumMonitors\n"));
9115
9116         /*
9117          * Enumerate the print monitors ...
9118          *
9119          * Just reply with "Local Port", to keep NT happy
9120          * and I can use my nice printer checker.
9121          */
9122
9123         *r->out.count = 0;
9124         *r->out.needed = 0;
9125         *r->out.info = NULL;
9126
9127         switch (r->in.level) {
9128         case 1:
9129                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9130                                                    r->out.count);
9131                 break;
9132         case 2:
9133                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9134                                                    r->out.count);
9135                 break;
9136         default:
9137                 return WERR_UNKNOWN_LEVEL;
9138         }
9139
9140         if (!W_ERROR_IS_OK(result)) {
9141                 return result;
9142         }
9143
9144         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9145                                                      spoolss_EnumMonitors,
9146                                                      *r->out.info, r->in.level,
9147                                                      *r->out.count);
9148         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9149         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9150
9151         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9152 }
9153
9154 /****************************************************************************
9155 ****************************************************************************/
9156
9157 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9158                              const print_queue_struct *queue,
9159                              int count, int snum,
9160                              struct spoolss_PrinterInfo2 *pinfo2,
9161                              uint32_t jobid,
9162                              struct spoolss_JobInfo1 *r)
9163 {
9164         int i = 0;
9165         bool found = false;
9166
9167         for (i=0; i<count; i++) {
9168                 if (queue[i].job == (int)jobid) {
9169                         found = true;
9170                         break;
9171                 }
9172         }
9173
9174         if (found == false) {
9175                 /* NT treats not found as bad param... yet another bad choice */
9176                 return WERR_INVALID_PARAM;
9177         }
9178
9179         return fill_job_info1(mem_ctx,
9180                               r,
9181                               &queue[i],
9182                               i,
9183                               snum,
9184                               pinfo2);
9185 }
9186
9187 /****************************************************************************
9188 ****************************************************************************/
9189
9190 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9191                              const print_queue_struct *queue,
9192                              int count, int snum,
9193                              struct spoolss_PrinterInfo2 *pinfo2,
9194                              uint32_t jobid,
9195                              struct spoolss_JobInfo2 *r)
9196 {
9197         int i = 0;
9198         bool found = false;
9199         struct spoolss_DeviceMode *devmode;
9200         WERROR result;
9201
9202         for (i=0; i<count; i++) {
9203                 if (queue[i].job == (int)jobid) {
9204                         found = true;
9205                         break;
9206                 }
9207         }
9208
9209         if (found == false) {
9210                 /* NT treats not found as bad param... yet another bad
9211                    choice */
9212                 return WERR_INVALID_PARAM;
9213         }
9214
9215         /*
9216          * if the print job does not have a DEVMODE associated with it,
9217          * just use the one for the printer. A NULL devicemode is not
9218          *  a failure condition
9219          */
9220
9221         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9222         if (!devmode) {
9223                 result = spoolss_create_default_devmode(mem_ctx,
9224                                                 pinfo2->printername,
9225                                                 &devmode);
9226                 if (!W_ERROR_IS_OK(result)) {
9227                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9228                         return result;
9229                 }
9230         }
9231
9232         return fill_job_info2(mem_ctx,
9233                               r,
9234                               &queue[i],
9235                               i,
9236                               snum,
9237                               pinfo2,
9238                               devmode);
9239 }
9240
9241 /****************************************************************
9242  _spoolss_GetJob
9243 ****************************************************************/
9244
9245 WERROR _spoolss_GetJob(struct pipes_struct *p,
9246                        struct spoolss_GetJob *r)
9247 {
9248         WERROR result = WERR_OK;
9249         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9250         int snum;
9251         int count;
9252         print_queue_struct      *queue = NULL;
9253         print_status_struct prt_status;
9254
9255         /* that's an [in out] buffer */
9256
9257         if (!r->in.buffer && (r->in.offered != 0)) {
9258                 return WERR_INVALID_PARAM;
9259         }
9260
9261         DEBUG(5,("_spoolss_GetJob\n"));
9262
9263         *r->out.needed = 0;
9264
9265         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9266                 return WERR_BADFID;
9267         }
9268
9269         result = winreg_get_printer_internal(p->mem_ctx,
9270                                     get_session_info_system(),
9271                                     p->msg_ctx,
9272                                     lp_const_servicename(snum),
9273                                     &pinfo2);
9274         if (!W_ERROR_IS_OK(result)) {
9275                 return result;
9276         }
9277
9278         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9279
9280         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9281                      count, prt_status.status, prt_status.message));
9282
9283         switch (r->in.level) {
9284         case 1:
9285                 result = getjob_level_1(p->mem_ctx,
9286                                         queue, count, snum, pinfo2,
9287                                         r->in.job_id, &r->out.info->info1);
9288                 break;
9289         case 2:
9290                 result = getjob_level_2(p->mem_ctx,
9291                                         queue, count, snum, pinfo2,
9292                                         r->in.job_id, &r->out.info->info2);
9293                 break;
9294         default:
9295                 result = WERR_UNKNOWN_LEVEL;
9296                 break;
9297         }
9298
9299         SAFE_FREE(queue);
9300         TALLOC_FREE(pinfo2);
9301
9302         if (!W_ERROR_IS_OK(result)) {
9303                 TALLOC_FREE(r->out.info);
9304                 return result;
9305         }
9306
9307         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9308                                                                                    r->in.level);
9309         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9310
9311         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9312 }
9313
9314 /****************************************************************
9315  _spoolss_GetPrinterDataEx
9316 ****************************************************************/
9317
9318 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9319                                  struct spoolss_GetPrinterDataEx *r)
9320 {
9321
9322         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9323         const char *printer;
9324         int                     snum = 0;
9325         WERROR result = WERR_OK;
9326         DATA_BLOB blob;
9327         enum winreg_Type val_type = REG_NONE;
9328         uint8_t *val_data = NULL;
9329         uint32_t val_size = 0;
9330         struct dcerpc_binding_handle *b;
9331         TALLOC_CTX *tmp_ctx;
9332
9333         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9334
9335         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9336                 r->in.key_name, r->in.value_name));
9337
9338         /* in case of problem, return some default values */
9339
9340         *r->out.needed  = 0;
9341         *r->out.type    = REG_NONE;
9342
9343         tmp_ctx = talloc_new(p->mem_ctx);
9344         if (!tmp_ctx) {
9345                 return WERR_NOMEM;
9346         }
9347
9348         if (!Printer) {
9349                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9350                         OUR_HANDLE(r->in.handle)));
9351                 result = WERR_BADFID;
9352                 goto done;
9353         }
9354
9355         /* check to see if the keyname is valid */
9356         if (!strlen(r->in.key_name)) {
9357                 result = WERR_INVALID_PARAM;
9358                 goto done;
9359         }
9360
9361         /* Is the handle to a printer or to the server? */
9362
9363         if (Printer->printer_type == SPLHND_SERVER) {
9364
9365                 union spoolss_PrinterData data;
9366
9367                 result = getprinterdata_printer_server(tmp_ctx,
9368                                                        r->in.value_name,
9369                                                        r->out.type,
9370                                                        &data);
9371                 if (!W_ERROR_IS_OK(result)) {
9372                         goto done;
9373                 }
9374
9375                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9376                                                   *r->out.type, &data);
9377                 if (!W_ERROR_IS_OK(result)) {
9378                         goto done;
9379                 }
9380
9381                 *r->out.needed = blob.length;
9382
9383                 if (r->in.offered >= *r->out.needed) {
9384                         memcpy(r->out.data, blob.data, blob.length);
9385                 }
9386
9387                 result = WERR_OK;
9388                 goto done;
9389         }
9390
9391         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9392                 result = WERR_BADFID;
9393                 goto done;
9394         }
9395         printer = lp_const_servicename(snum);
9396
9397         result = winreg_printer_binding_handle(tmp_ctx,
9398                                                get_session_info_system(),
9399                                                p->msg_ctx,
9400                                                &b);
9401         if (!W_ERROR_IS_OK(result)) {
9402                 goto done;
9403         }
9404
9405         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9406         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9407             strequal(r->in.value_name, "ChangeId")) {
9408                 *r->out.type = REG_DWORD;
9409                 *r->out.needed = 4;
9410                 if (r->in.offered >= *r->out.needed) {
9411                         uint32_t changeid = 0;
9412
9413                         result = winreg_printer_get_changeid(tmp_ctx, b,
9414                                                              printer,
9415                                                              &changeid);
9416                         if (!W_ERROR_IS_OK(result)) {
9417                                 goto done;
9418                         }
9419
9420                         SIVAL(r->out.data, 0, changeid);
9421                         result = WERR_OK;
9422                 }
9423                 goto done;
9424         }
9425
9426         result = winreg_get_printer_dataex(tmp_ctx, b,
9427                                            printer,
9428                                            r->in.key_name,
9429                                            r->in.value_name,
9430                                            &val_type,
9431                                            &val_data,
9432                                            &val_size);
9433         if (!W_ERROR_IS_OK(result)) {
9434                 goto done;
9435         }
9436
9437         *r->out.needed = val_size;
9438         *r->out.type = val_type;
9439
9440         if (r->in.offered >= *r->out.needed) {
9441                 memcpy(r->out.data, val_data, val_size);
9442         }
9443
9444 done:
9445         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9446
9447         if (W_ERROR_IS_OK(result)) {
9448                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9449         }
9450
9451         talloc_free(tmp_ctx);
9452         return result;
9453 }
9454
9455 /****************************************************************
9456  _spoolss_SetPrinterDataEx
9457 ****************************************************************/
9458
9459 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9460                                  struct spoolss_SetPrinterDataEx *r)
9461 {
9462         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9463         int                     snum = 0;
9464         WERROR                  result = WERR_OK;
9465         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9466         char                    *oid_string;
9467         struct dcerpc_binding_handle *b;
9468         TALLOC_CTX *tmp_ctx;
9469
9470         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9471
9472         /* From MSDN documentation of SetPrinterDataEx: pass request to
9473            SetPrinterData if key is "PrinterDriverData" */
9474
9475         if (!Printer) {
9476                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9477                         OUR_HANDLE(r->in.handle)));
9478                 return WERR_BADFID;
9479         }
9480
9481         if (Printer->printer_type == SPLHND_SERVER) {
9482                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9483                         "Not implemented for server handles yet\n"));
9484                 return WERR_INVALID_PARAM;
9485         }
9486
9487         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9488                 return WERR_BADFID;
9489         }
9490
9491         /*
9492          * Access check : NT returns "access denied" if you make a
9493          * SetPrinterData call without the necessary privildge.
9494          * we were originally returning OK if nothing changed
9495          * which made Win2k issue **a lot** of SetPrinterData
9496          * when connecting to a printer  --jerry
9497          */
9498
9499         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9500                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9501                         "change denied by handle access permissions\n"));
9502                 return WERR_ACCESS_DENIED;
9503         }
9504
9505         tmp_ctx = talloc_new(p->mem_ctx);
9506         if (!tmp_ctx) {
9507                 return WERR_NOMEM;
9508         }
9509
9510         result = winreg_printer_binding_handle(tmp_ctx,
9511                                                get_session_info_system(),
9512                                                p->msg_ctx,
9513                                                &b);
9514         if (!W_ERROR_IS_OK(result)) {
9515                 goto done;
9516         }
9517
9518         result = winreg_get_printer(tmp_ctx, b,
9519                                     lp_servicename(snum),
9520                                     &pinfo2);
9521         if (!W_ERROR_IS_OK(result)) {
9522                 goto done;
9523         }
9524
9525         /* check for OID in valuename */
9526
9527         oid_string = strchr(r->in.value_name, ',');
9528         if (oid_string) {
9529                 *oid_string = '\0';
9530                 oid_string++;
9531         }
9532
9533         /* save the registry data */
9534
9535         result = winreg_set_printer_dataex(tmp_ctx, b,
9536                                            pinfo2->sharename,
9537                                            r->in.key_name,
9538                                            r->in.value_name,
9539                                            r->in.type,
9540                                            r->in.data,
9541                                            r->in.offered);
9542
9543         if (W_ERROR_IS_OK(result)) {
9544                 /* save the OID if one was specified */
9545                 if (oid_string) {
9546                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9547                                 r->in.key_name, SPOOL_OID_KEY);
9548                         if (!str) {
9549                                 result = WERR_NOMEM;
9550                                 goto done;
9551                         }
9552
9553                         /*
9554                          * I'm not checking the status here on purpose.  Don't know
9555                          * if this is right, but I'm returning the status from the
9556                          * previous set_printer_dataex() call.  I have no idea if
9557                          * this is right.    --jerry
9558                          */
9559                         winreg_set_printer_dataex(tmp_ctx, b,
9560                                                   pinfo2->sharename,
9561                                                   str,
9562                                                   r->in.value_name,
9563                                                   REG_SZ,
9564                                                   (uint8_t *) oid_string,
9565                                                   strlen(oid_string) + 1);
9566                 }
9567
9568                 result = winreg_printer_update_changeid(tmp_ctx, b,
9569                                                         lp_const_servicename(snum));
9570
9571         }
9572
9573 done:
9574         talloc_free(tmp_ctx);
9575         return result;
9576 }
9577
9578 /****************************************************************
9579  _spoolss_DeletePrinterDataEx
9580 ****************************************************************/
9581
9582 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9583                                     struct spoolss_DeletePrinterDataEx *r)
9584 {
9585         const char *printer;
9586         int             snum=0;
9587         WERROR          status = WERR_OK;
9588         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9589
9590         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9591
9592         if (!Printer) {
9593                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9594                         "Invalid handle (%s:%u:%u).\n",
9595                         OUR_HANDLE(r->in.handle)));
9596                 return WERR_BADFID;
9597         }
9598
9599         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9600                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9601                         "printer properties change denied by handle\n"));
9602                 return WERR_ACCESS_DENIED;
9603         }
9604
9605         if (!r->in.value_name || !r->in.key_name) {
9606                 return WERR_NOMEM;
9607         }
9608
9609         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9610                 return WERR_BADFID;
9611         }
9612         printer = lp_const_servicename(snum);
9613
9614         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9615                                               get_session_info_system(),
9616                                               p->msg_ctx,
9617                                               printer,
9618                                               r->in.key_name,
9619                                               r->in.value_name);
9620         if (W_ERROR_IS_OK(status)) {
9621                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9622                                                         get_session_info_system(),
9623                                                         p->msg_ctx,
9624                                                         printer);
9625         }
9626
9627         return status;
9628 }
9629
9630 /****************************************************************
9631  _spoolss_EnumPrinterKey
9632 ****************************************************************/
9633
9634 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9635                                struct spoolss_EnumPrinterKey *r)
9636 {
9637         uint32_t        num_keys;
9638         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9639         int             snum = 0;
9640         WERROR          result = WERR_BADFILE;
9641         const char **array = NULL;
9642         DATA_BLOB blob;
9643
9644         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9645
9646         if (!Printer) {
9647                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9648                         OUR_HANDLE(r->in.handle)));
9649                 return WERR_BADFID;
9650         }
9651
9652         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9653                 return WERR_BADFID;
9654         }
9655
9656         result = winreg_enum_printer_key_internal(p->mem_ctx,
9657                                          get_session_info_system(),
9658                                          p->msg_ctx,
9659                                          lp_const_servicename(snum),
9660                                          r->in.key_name,
9661                                          &num_keys,
9662                                          &array);
9663         if (!W_ERROR_IS_OK(result)) {
9664                 goto done;
9665         }
9666
9667         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9668                 result = WERR_NOMEM;
9669                 goto done;
9670         }
9671
9672         *r->out._ndr_size = r->in.offered / 2;
9673         *r->out.needed = blob.length;
9674
9675         if (r->in.offered < *r->out.needed) {
9676                 result = WERR_MORE_DATA;
9677         } else {
9678                 result = WERR_OK;
9679                 r->out.key_buffer->string_array = array;
9680         }
9681
9682  done:
9683         if (!W_ERROR_IS_OK(result)) {
9684                 TALLOC_FREE(array);
9685                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9686                         *r->out.needed = 0;
9687                 }
9688         }
9689
9690         return result;
9691 }
9692
9693 /****************************************************************
9694  _spoolss_DeletePrinterKey
9695 ****************************************************************/
9696
9697 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9698                                  struct spoolss_DeletePrinterKey *r)
9699 {
9700         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9701         int                     snum=0;
9702         WERROR                  status;
9703         const char *printer;
9704         struct dcerpc_binding_handle *b;
9705         TALLOC_CTX *tmp_ctx;
9706
9707         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9708
9709         if (!Printer) {
9710                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9711                         OUR_HANDLE(r->in.handle)));
9712                 return WERR_BADFID;
9713         }
9714
9715         /* if keyname == NULL, return error */
9716         if ( !r->in.key_name )
9717                 return WERR_INVALID_PARAM;
9718
9719         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9720                 return WERR_BADFID;
9721         }
9722
9723         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9724                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9725                         "printer properties change denied by handle\n"));
9726                 return WERR_ACCESS_DENIED;
9727         }
9728
9729         printer = lp_const_servicename(snum);
9730
9731         tmp_ctx = talloc_new(p->mem_ctx);
9732         if (!tmp_ctx) {
9733                 return WERR_NOMEM;
9734         }
9735
9736         status = winreg_printer_binding_handle(tmp_ctx,
9737                                                get_session_info_system(),
9738                                                p->msg_ctx,
9739                                                &b);
9740         if (!W_ERROR_IS_OK(status)) {
9741                 goto done;
9742         }
9743
9744         /* delete the key and all subkeys */
9745         status = winreg_delete_printer_key(tmp_ctx, b,
9746                                            printer,
9747                                            r->in.key_name);
9748         if (W_ERROR_IS_OK(status)) {
9749                 status = winreg_printer_update_changeid(tmp_ctx, b,
9750                                                         printer);
9751         }
9752
9753 done:
9754         talloc_free(tmp_ctx);
9755         return status;
9756 }
9757
9758 /****************************************************************
9759  _spoolss_EnumPrinterDataEx
9760 ****************************************************************/
9761
9762 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9763                                   struct spoolss_EnumPrinterDataEx *r)
9764 {
9765         uint32_t        count = 0;
9766         struct spoolss_PrinterEnumValues *info = NULL;
9767         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9768         int             snum;
9769         WERROR          result;
9770
9771         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9772
9773         *r->out.count = 0;
9774         *r->out.needed = 0;
9775         *r->out.info = NULL;
9776
9777         if (!Printer) {
9778                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9779                         OUR_HANDLE(r->in.handle)));
9780                 return WERR_BADFID;
9781         }
9782
9783         /*
9784          * first check for a keyname of NULL or "".  Win2k seems to send
9785          * this a lot and we should send back WERR_INVALID_PARAM
9786          * no need to spend time looking up the printer in this case.
9787          * --jerry
9788          */
9789
9790         if (!strlen(r->in.key_name)) {
9791                 result = WERR_INVALID_PARAM;
9792                 goto done;
9793         }
9794
9795         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9796                 return WERR_BADFID;
9797         }
9798
9799         /* now look for a match on the key name */
9800         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9801                                             get_session_info_system(),
9802                                             p->msg_ctx,
9803                                             lp_const_servicename(snum),
9804                                             r->in.key_name,
9805                                             &count,
9806                                             &info);
9807         if (!W_ERROR_IS_OK(result)) {
9808                 goto done;
9809         }
9810
9811 #if 0 /* FIXME - gd */
9812         /* housekeeping information in the reply */
9813
9814         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9815          * the hand marshalled container size is a multiple
9816          * of 4 bytes for RPC alignment.
9817          */
9818
9819         if (needed % 4) {
9820                 needed += 4-(needed % 4);
9821         }
9822 #endif
9823         *r->out.count   = count;
9824         *r->out.info    = info;
9825
9826  done:
9827         if (!W_ERROR_IS_OK(result)) {
9828                 return result;
9829         }
9830
9831         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9832                                                spoolss_EnumPrinterDataEx,
9833                                                *r->out.info,
9834                                                *r->out.count);
9835         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9836         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9837
9838         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9839 }
9840
9841 /****************************************************************************
9842 ****************************************************************************/
9843
9844 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9845                                                  const char *servername,
9846                                                  const char *environment,
9847                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9848 {
9849         WERROR werr;
9850         char *path = NULL;
9851
9852         werr = compose_spoolss_server_path(mem_ctx,
9853                                            servername,
9854                                            environment,
9855                                            SPOOLSS_PRTPROCS_PATH,
9856                                            &path);
9857         if (!W_ERROR_IS_OK(werr)) {
9858                 return werr;
9859         }
9860
9861         DEBUG(4,("print processor directory: [%s]\n", path));
9862
9863         r->directory_name = path;
9864
9865         return WERR_OK;
9866 }
9867
9868 /****************************************************************
9869  _spoolss_GetPrintProcessorDirectory
9870 ****************************************************************/
9871
9872 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9873                                            struct spoolss_GetPrintProcessorDirectory *r)
9874 {
9875         WERROR result;
9876         char *prnproc_share = NULL;
9877         bool prnproc_share_exists = false;
9878         int snum;
9879
9880         /* that's an [in out] buffer */
9881
9882         if (!r->in.buffer && (r->in.offered != 0)) {
9883                 return WERR_INVALID_PARAM;
9884         }
9885
9886         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9887                 r->in.level));
9888
9889         *r->out.needed = 0;
9890
9891         /* r->in.level is ignored */
9892
9893         /* We always should reply with a local print processor directory so that
9894          * users are not forced to have a [prnproc$] share on the Samba spoolss
9895          * server, if users decide to do so, lets announce it though - Guenther */
9896
9897         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9898         if (!prnproc_share) {
9899                 return WERR_NOMEM;
9900         }
9901         if (snum != -1) {
9902                 prnproc_share_exists = true;
9903         }
9904
9905         result = getprintprocessordirectory_level_1(p->mem_ctx,
9906                                                     prnproc_share_exists ? r->in.server : NULL,
9907                                                     r->in.environment,
9908                                                     &r->out.info->info1);
9909         if (!W_ERROR_IS_OK(result)) {
9910                 TALLOC_FREE(r->out.info);
9911                 return result;
9912         }
9913
9914         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9915                                                                                    r->out.info, r->in.level);
9916         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9917
9918         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9919 }
9920
9921 /*******************************************************************
9922  ********************************************************************/
9923
9924 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9925                                const char *dllname)
9926 {
9927         enum ndr_err_code ndr_err;
9928         struct spoolss_MonitorUi ui;
9929
9930         ui.dll_name = dllname;
9931
9932         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9933                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9934         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9935                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9936         }
9937         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9938 }
9939
9940 /*******************************************************************
9941  Streams the monitor UI DLL name in UNICODE
9942 *******************************************************************/
9943
9944 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9945                                struct security_token *token, DATA_BLOB *in,
9946                                DATA_BLOB *out, uint32_t *needed)
9947 {
9948         const char *dllname = "tcpmonui.dll";
9949
9950         *needed = (strlen(dllname)+1) * 2;
9951
9952         if (out->length < *needed) {
9953                 return WERR_INSUFFICIENT_BUFFER;
9954         }
9955
9956         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9957                 return WERR_NOMEM;
9958         }
9959
9960         return WERR_OK;
9961 }
9962
9963 /*******************************************************************
9964  ********************************************************************/
9965
9966 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9967                              struct spoolss_PortData1 *port1,
9968                              const DATA_BLOB *buf)
9969 {
9970         enum ndr_err_code ndr_err;
9971         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9972                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9973         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9974                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9975         }
9976         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9977 }
9978
9979 /*******************************************************************
9980  ********************************************************************/
9981
9982 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9983                              struct spoolss_PortData2 *port2,
9984                              const DATA_BLOB *buf)
9985 {
9986         enum ndr_err_code ndr_err;
9987         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9988                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9989         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9990                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9991         }
9992         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9993 }
9994
9995 /*******************************************************************
9996  Create a new TCP/IP port
9997 *******************************************************************/
9998
9999 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10000                              struct security_token *token, DATA_BLOB *in,
10001                              DATA_BLOB *out, uint32_t *needed)
10002 {
10003         struct spoolss_PortData1 port1;
10004         struct spoolss_PortData2 port2;
10005         char *device_uri = NULL;
10006         uint32_t version;
10007
10008         const char *portname;
10009         const char *hostaddress;
10010         const char *queue;
10011         uint32_t port_number;
10012         uint32_t protocol;
10013
10014         /* peek for spoolss_PortData version */
10015
10016         if (!in || (in->length < (128 + 4))) {
10017                 return WERR_GENERAL_FAILURE;
10018         }
10019
10020         version = IVAL(in->data, 128);
10021
10022         switch (version) {
10023                 case 1:
10024                         ZERO_STRUCT(port1);
10025
10026                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10027                                 return WERR_NOMEM;
10028                         }
10029
10030                         portname        = port1.portname;
10031                         hostaddress     = port1.hostaddress;
10032                         queue           = port1.queue;
10033                         protocol        = port1.protocol;
10034                         port_number     = port1.port_number;
10035
10036                         break;
10037                 case 2:
10038                         ZERO_STRUCT(port2);
10039
10040                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10041                                 return WERR_NOMEM;
10042                         }
10043
10044                         portname        = port2.portname;
10045                         hostaddress     = port2.hostaddress;
10046                         queue           = port2.queue;
10047                         protocol        = port2.protocol;
10048                         port_number     = port2.port_number;
10049
10050                         break;
10051                 default:
10052                         DEBUG(1,("xcvtcp_addport: "
10053                                 "unknown version of port_data: %d\n", version));
10054                         return WERR_UNKNOWN_PORT;
10055         }
10056
10057         /* create the device URI and call the add_port_hook() */
10058
10059         switch (protocol) {
10060         case PROTOCOL_RAWTCP_TYPE:
10061                 device_uri = talloc_asprintf(mem_ctx,
10062                                 "socket://%s:%d/", hostaddress,
10063                                 port_number);
10064                 break;
10065
10066         case PROTOCOL_LPR_TYPE:
10067                 device_uri = talloc_asprintf(mem_ctx,
10068                         "lpr://%s/%s", hostaddress, queue );
10069                 break;
10070
10071         default:
10072                 return WERR_UNKNOWN_PORT;
10073         }
10074
10075         if (!device_uri) {
10076                 return WERR_NOMEM;
10077         }
10078
10079         return add_port_hook(mem_ctx, token, portname, device_uri);
10080 }
10081
10082 /*******************************************************************
10083 *******************************************************************/
10084
10085 struct xcv_api_table xcvtcp_cmds[] = {
10086         { "MonitorUI",  xcvtcp_monitorui },
10087         { "AddPort",    xcvtcp_addport},
10088         { NULL,         NULL }
10089 };
10090
10091 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10092                                      struct security_token *token, const char *command,
10093                                      DATA_BLOB *inbuf,
10094                                      DATA_BLOB *outbuf,
10095                                      uint32_t *needed )
10096 {
10097         int i;
10098
10099         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10100
10101         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10102                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10103                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10104         }
10105
10106         return WERR_BADFUNC;
10107 }
10108
10109 /*******************************************************************
10110 *******************************************************************/
10111 #if 0   /* don't support management using the "Local Port" monitor */
10112
10113 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10114                                  struct security_token *token, DATA_BLOB *in,
10115                                  DATA_BLOB *out, uint32_t *needed)
10116 {
10117         const char *dllname = "localui.dll";
10118
10119         *needed = (strlen(dllname)+1) * 2;
10120
10121         if (out->length < *needed) {
10122                 return WERR_INSUFFICIENT_BUFFER;
10123         }
10124
10125         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10126                 return WERR_NOMEM;
10127         }
10128
10129         return WERR_OK;
10130 }
10131
10132 /*******************************************************************
10133 *******************************************************************/
10134
10135 struct xcv_api_table xcvlocal_cmds[] = {
10136         { "MonitorUI",  xcvlocal_monitorui },
10137         { NULL,         NULL }
10138 };
10139 #else
10140 struct xcv_api_table xcvlocal_cmds[] = {
10141         { NULL,         NULL }
10142 };
10143 #endif
10144
10145
10146
10147 /*******************************************************************
10148 *******************************************************************/
10149
10150 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10151                                        struct security_token *token, const char *command,
10152                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10153                                        uint32_t *needed)
10154 {
10155         int i;
10156
10157         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10158
10159         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10160                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10161                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10162         }
10163         return WERR_BADFUNC;
10164 }
10165
10166 /****************************************************************
10167  _spoolss_XcvData
10168 ****************************************************************/
10169
10170 WERROR _spoolss_XcvData(struct pipes_struct *p,
10171                         struct spoolss_XcvData *r)
10172 {
10173         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10174         DATA_BLOB out_data = data_blob_null;
10175         WERROR werror;
10176
10177         if (!Printer) {
10178                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10179                         OUR_HANDLE(r->in.handle)));
10180                 return WERR_BADFID;
10181         }
10182
10183         /* Has to be a handle to the TCP/IP port monitor */
10184
10185         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10186                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10187                 return WERR_BADFID;
10188         }
10189
10190         /* requires administrative access to the server */
10191
10192         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10193                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10194                 return WERR_ACCESS_DENIED;
10195         }
10196
10197         /* Allocate the outgoing buffer */
10198
10199         if (r->in.out_data_size) {
10200                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10201                 if (out_data.data == NULL) {
10202                         return WERR_NOMEM;
10203                 }
10204         }
10205
10206         switch ( Printer->printer_type ) {
10207         case SPLHND_PORTMON_TCP:
10208                 werror = process_xcvtcp_command(p->mem_ctx,
10209                                                 p->session_info->security_token,
10210                                                 r->in.function_name,
10211                                                 &r->in.in_data, &out_data,
10212                                                 r->out.needed);
10213                 break;
10214         case SPLHND_PORTMON_LOCAL:
10215                 werror = process_xcvlocal_command(p->mem_ctx,
10216                                                   p->session_info->security_token,
10217                                                   r->in.function_name,
10218                                                   &r->in.in_data, &out_data,
10219                                                   r->out.needed);
10220                 break;
10221         default:
10222                 werror = WERR_INVALID_PRINT_MONITOR;
10223         }
10224
10225         if (!W_ERROR_IS_OK(werror)) {
10226                 return werror;
10227         }
10228
10229         *r->out.status_code = 0;
10230
10231         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10232                 memcpy(r->out.out_data, out_data.data,
10233                         MIN(r->in.out_data_size, out_data.length));
10234         }
10235
10236         return WERR_OK;
10237 }
10238
10239 /****************************************************************
10240  _spoolss_AddPrintProcessor
10241 ****************************************************************/
10242
10243 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10244                                   struct spoolss_AddPrintProcessor *r)
10245 {
10246         /* for now, just indicate success and ignore the add.  We'll
10247            automatically set the winprint processor for printer
10248            entries later.  Used to debug the LexMark Optra S 1855 PCL
10249            driver --jerry */
10250
10251         return WERR_OK;
10252 }
10253
10254 /****************************************************************
10255  _spoolss_AddPort
10256 ****************************************************************/
10257
10258 WERROR _spoolss_AddPort(struct pipes_struct *p,
10259                         struct spoolss_AddPort *r)
10260 {
10261         /* do what w2k3 does */
10262
10263         return WERR_NOT_SUPPORTED;
10264 }
10265
10266 /****************************************************************
10267  _spoolss_GetPrinterDriver
10268 ****************************************************************/
10269
10270 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10271                                  struct spoolss_GetPrinterDriver *r)
10272 {
10273         p->rng_fault_state = true;
10274         return WERR_NOT_SUPPORTED;
10275 }
10276
10277 /****************************************************************
10278  _spoolss_ReadPrinter
10279 ****************************************************************/
10280
10281 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10282                             struct spoolss_ReadPrinter *r)
10283 {
10284         p->rng_fault_state = true;
10285         return WERR_NOT_SUPPORTED;
10286 }
10287
10288 /****************************************************************
10289  _spoolss_WaitForPrinterChange
10290 ****************************************************************/
10291
10292 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10293                                      struct spoolss_WaitForPrinterChange *r)
10294 {
10295         p->rng_fault_state = true;
10296         return WERR_NOT_SUPPORTED;
10297 }
10298
10299 /****************************************************************
10300  _spoolss_ConfigurePort
10301 ****************************************************************/
10302
10303 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10304                               struct spoolss_ConfigurePort *r)
10305 {
10306         p->rng_fault_state = true;
10307         return WERR_NOT_SUPPORTED;
10308 }
10309
10310 /****************************************************************
10311  _spoolss_DeletePort
10312 ****************************************************************/
10313
10314 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10315                            struct spoolss_DeletePort *r)
10316 {
10317         p->rng_fault_state = true;
10318         return WERR_NOT_SUPPORTED;
10319 }
10320
10321 /****************************************************************
10322  _spoolss_CreatePrinterIC
10323 ****************************************************************/
10324
10325 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10326                                 struct spoolss_CreatePrinterIC *r)
10327 {
10328         p->rng_fault_state = true;
10329         return WERR_NOT_SUPPORTED;
10330 }
10331
10332 /****************************************************************
10333  _spoolss_PlayGDIScriptOnPrinterIC
10334 ****************************************************************/
10335
10336 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10337                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10338 {
10339         p->rng_fault_state = true;
10340         return WERR_NOT_SUPPORTED;
10341 }
10342
10343 /****************************************************************
10344  _spoolss_DeletePrinterIC
10345 ****************************************************************/
10346
10347 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10348                                 struct spoolss_DeletePrinterIC *r)
10349 {
10350         p->rng_fault_state = true;
10351         return WERR_NOT_SUPPORTED;
10352 }
10353
10354 /****************************************************************
10355  _spoolss_AddPrinterConnection
10356 ****************************************************************/
10357
10358 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10359                                      struct spoolss_AddPrinterConnection *r)
10360 {
10361         p->rng_fault_state = true;
10362         return WERR_NOT_SUPPORTED;
10363 }
10364
10365 /****************************************************************
10366  _spoolss_DeletePrinterConnection
10367 ****************************************************************/
10368
10369 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10370                                         struct spoolss_DeletePrinterConnection *r)
10371 {
10372         p->rng_fault_state = true;
10373         return WERR_NOT_SUPPORTED;
10374 }
10375
10376 /****************************************************************
10377  _spoolss_PrinterMessageBox
10378 ****************************************************************/
10379
10380 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10381                                   struct spoolss_PrinterMessageBox *r)
10382 {
10383         p->rng_fault_state = true;
10384         return WERR_NOT_SUPPORTED;
10385 }
10386
10387 /****************************************************************
10388  _spoolss_AddMonitor
10389 ****************************************************************/
10390
10391 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10392                            struct spoolss_AddMonitor *r)
10393 {
10394         p->rng_fault_state = true;
10395         return WERR_NOT_SUPPORTED;
10396 }
10397
10398 /****************************************************************
10399  _spoolss_DeleteMonitor
10400 ****************************************************************/
10401
10402 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10403                               struct spoolss_DeleteMonitor *r)
10404 {
10405         p->rng_fault_state = true;
10406         return WERR_NOT_SUPPORTED;
10407 }
10408
10409 /****************************************************************
10410  _spoolss_DeletePrintProcessor
10411 ****************************************************************/
10412
10413 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10414                                      struct spoolss_DeletePrintProcessor *r)
10415 {
10416         p->rng_fault_state = true;
10417         return WERR_NOT_SUPPORTED;
10418 }
10419
10420 /****************************************************************
10421  _spoolss_AddPrintProvidor
10422 ****************************************************************/
10423
10424 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10425                                  struct spoolss_AddPrintProvidor *r)
10426 {
10427         p->rng_fault_state = true;
10428         return WERR_NOT_SUPPORTED;
10429 }
10430
10431 /****************************************************************
10432  _spoolss_DeletePrintProvidor
10433 ****************************************************************/
10434
10435 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10436                                     struct spoolss_DeletePrintProvidor *r)
10437 {
10438         p->rng_fault_state = true;
10439         return WERR_NOT_SUPPORTED;
10440 }
10441
10442 /****************************************************************
10443  _spoolss_FindFirstPrinterChangeNotification
10444 ****************************************************************/
10445
10446 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10447                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10448 {
10449         p->rng_fault_state = true;
10450         return WERR_NOT_SUPPORTED;
10451 }
10452
10453 /****************************************************************
10454  _spoolss_FindNextPrinterChangeNotification
10455 ****************************************************************/
10456
10457 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10458                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10459 {
10460         p->rng_fault_state = true;
10461         return WERR_NOT_SUPPORTED;
10462 }
10463
10464 /****************************************************************
10465  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10466 ****************************************************************/
10467
10468 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10469                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10470 {
10471         p->rng_fault_state = true;
10472         return WERR_NOT_SUPPORTED;
10473 }
10474
10475 /****************************************************************
10476  _spoolss_ReplyOpenPrinter
10477 ****************************************************************/
10478
10479 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10480                                  struct spoolss_ReplyOpenPrinter *r)
10481 {
10482         p->rng_fault_state = true;
10483         return WERR_NOT_SUPPORTED;
10484 }
10485
10486 /****************************************************************
10487  _spoolss_RouterReplyPrinter
10488 ****************************************************************/
10489
10490 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10491                                    struct spoolss_RouterReplyPrinter *r)
10492 {
10493         p->rng_fault_state = true;
10494         return WERR_NOT_SUPPORTED;
10495 }
10496
10497 /****************************************************************
10498  _spoolss_ReplyClosePrinter
10499 ****************************************************************/
10500
10501 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10502                                   struct spoolss_ReplyClosePrinter *r)
10503 {
10504         p->rng_fault_state = true;
10505         return WERR_NOT_SUPPORTED;
10506 }
10507
10508 /****************************************************************
10509  _spoolss_AddPortEx
10510 ****************************************************************/
10511
10512 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10513                           struct spoolss_AddPortEx *r)
10514 {
10515         p->rng_fault_state = true;
10516         return WERR_NOT_SUPPORTED;
10517 }
10518
10519 /****************************************************************
10520  _spoolss_RouterFindFirstPrinterChangeNotification
10521 ****************************************************************/
10522
10523 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10524                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10525 {
10526         p->rng_fault_state = true;
10527         return WERR_NOT_SUPPORTED;
10528 }
10529
10530 /****************************************************************
10531  _spoolss_SpoolerInit
10532 ****************************************************************/
10533
10534 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10535                             struct spoolss_SpoolerInit *r)
10536 {
10537         p->rng_fault_state = true;
10538         return WERR_NOT_SUPPORTED;
10539 }
10540
10541 /****************************************************************
10542  _spoolss_ResetPrinterEx
10543 ****************************************************************/
10544
10545 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10546                                struct spoolss_ResetPrinterEx *r)
10547 {
10548         p->rng_fault_state = true;
10549         return WERR_NOT_SUPPORTED;
10550 }
10551
10552 /****************************************************************
10553  _spoolss_RouterReplyPrinterEx
10554 ****************************************************************/
10555
10556 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10557                                      struct spoolss_RouterReplyPrinterEx *r)
10558 {
10559         p->rng_fault_state = true;
10560         return WERR_NOT_SUPPORTED;
10561 }
10562
10563 /****************************************************************
10564  _spoolss_44
10565 ****************************************************************/
10566
10567 WERROR _spoolss_44(struct pipes_struct *p,
10568                    struct spoolss_44 *r)
10569 {
10570         p->rng_fault_state = true;
10571         return WERR_NOT_SUPPORTED;
10572 }
10573
10574 /****************************************************************
10575  _spoolss_SetPort
10576 ****************************************************************/
10577
10578 WERROR _spoolss_SetPort(struct pipes_struct *p,
10579                         struct spoolss_SetPort *r)
10580 {
10581         p->rng_fault_state = true;
10582         return WERR_NOT_SUPPORTED;
10583 }
10584
10585 /****************************************************************
10586  _spoolss_4a
10587 ****************************************************************/
10588
10589 WERROR _spoolss_4a(struct pipes_struct *p,
10590                    struct spoolss_4a *r)
10591 {
10592         p->rng_fault_state = true;
10593         return WERR_NOT_SUPPORTED;
10594 }
10595
10596 /****************************************************************
10597  _spoolss_4b
10598 ****************************************************************/
10599
10600 WERROR _spoolss_4b(struct pipes_struct *p,
10601                    struct spoolss_4b *r)
10602 {
10603         p->rng_fault_state = true;
10604         return WERR_NOT_SUPPORTED;
10605 }
10606
10607 /****************************************************************
10608  _spoolss_4c
10609 ****************************************************************/
10610
10611 WERROR _spoolss_4c(struct pipes_struct *p,
10612                    struct spoolss_4c *r)
10613 {
10614         p->rng_fault_state = true;
10615         return WERR_NOT_SUPPORTED;
10616 }
10617
10618 /****************************************************************
10619  _spoolss_53
10620 ****************************************************************/
10621
10622 WERROR _spoolss_53(struct pipes_struct *p,
10623                    struct spoolss_53 *r)
10624 {
10625         p->rng_fault_state = true;
10626         return WERR_NOT_SUPPORTED;
10627 }
10628
10629 /****************************************************************
10630  _spoolss_AddPerMachineConnection
10631 ****************************************************************/
10632
10633 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10634                                         struct spoolss_AddPerMachineConnection *r)
10635 {
10636         p->rng_fault_state = true;
10637         return WERR_NOT_SUPPORTED;
10638 }
10639
10640 /****************************************************************
10641  _spoolss_DeletePerMachineConnection
10642 ****************************************************************/
10643
10644 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10645                                            struct spoolss_DeletePerMachineConnection *r)
10646 {
10647         p->rng_fault_state = true;
10648         return WERR_NOT_SUPPORTED;
10649 }
10650
10651 /****************************************************************
10652  _spoolss_EnumPerMachineConnections
10653 ****************************************************************/
10654
10655 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10656                                           struct spoolss_EnumPerMachineConnections *r)
10657 {
10658         p->rng_fault_state = true;
10659         return WERR_NOT_SUPPORTED;
10660 }
10661
10662 /****************************************************************
10663  _spoolss_5a
10664 ****************************************************************/
10665
10666 WERROR _spoolss_5a(struct pipes_struct *p,
10667                    struct spoolss_5a *r)
10668 {
10669         p->rng_fault_state = true;
10670         return WERR_NOT_SUPPORTED;
10671 }
10672
10673 /****************************************************************
10674  _spoolss_5b
10675 ****************************************************************/
10676
10677 WERROR _spoolss_5b(struct pipes_struct *p,
10678                    struct spoolss_5b *r)
10679 {
10680         p->rng_fault_state = true;
10681         return WERR_NOT_SUPPORTED;
10682 }
10683
10684 /****************************************************************
10685  _spoolss_5c
10686 ****************************************************************/
10687
10688 WERROR _spoolss_5c(struct pipes_struct *p,
10689                    struct spoolss_5c *r)
10690 {
10691         p->rng_fault_state = true;
10692         return WERR_NOT_SUPPORTED;
10693 }
10694
10695 /****************************************************************
10696  _spoolss_5d
10697 ****************************************************************/
10698
10699 WERROR _spoolss_5d(struct pipes_struct *p,
10700                    struct spoolss_5d *r)
10701 {
10702         p->rng_fault_state = true;
10703         return WERR_NOT_SUPPORTED;
10704 }
10705
10706 /****************************************************************
10707  _spoolss_5e
10708 ****************************************************************/
10709
10710 WERROR _spoolss_5e(struct pipes_struct *p,
10711                    struct spoolss_5e *r)
10712 {
10713         p->rng_fault_state = true;
10714         return WERR_NOT_SUPPORTED;
10715 }
10716
10717 /****************************************************************
10718  _spoolss_5f
10719 ****************************************************************/
10720
10721 WERROR _spoolss_5f(struct pipes_struct *p,
10722                    struct spoolss_5f *r)
10723 {
10724         p->rng_fault_state = true;
10725         return WERR_NOT_SUPPORTED;
10726 }
10727
10728 /****************************************************************
10729  _spoolss_60
10730 ****************************************************************/
10731
10732 WERROR _spoolss_60(struct pipes_struct *p,
10733                    struct spoolss_60 *r)
10734 {
10735         p->rng_fault_state = true;
10736         return WERR_NOT_SUPPORTED;
10737 }
10738
10739 /****************************************************************
10740  _spoolss_61
10741 ****************************************************************/
10742
10743 WERROR _spoolss_61(struct pipes_struct *p,
10744                    struct spoolss_61 *r)
10745 {
10746         p->rng_fault_state = true;
10747         return WERR_NOT_SUPPORTED;
10748 }
10749
10750 /****************************************************************
10751  _spoolss_62
10752 ****************************************************************/
10753
10754 WERROR _spoolss_62(struct pipes_struct *p,
10755                    struct spoolss_62 *r)
10756 {
10757         p->rng_fault_state = true;
10758         return WERR_NOT_SUPPORTED;
10759 }
10760
10761 /****************************************************************
10762  _spoolss_63
10763 ****************************************************************/
10764
10765 WERROR _spoolss_63(struct pipes_struct *p,
10766                    struct spoolss_63 *r)
10767 {
10768         p->rng_fault_state = true;
10769         return WERR_NOT_SUPPORTED;
10770 }
10771
10772 /****************************************************************
10773  _spoolss_64
10774 ****************************************************************/
10775
10776 WERROR _spoolss_64(struct pipes_struct *p,
10777                    struct spoolss_64 *r)
10778 {
10779         p->rng_fault_state = true;
10780         return WERR_NOT_SUPPORTED;
10781 }
10782
10783 /****************************************************************
10784  _spoolss_65
10785 ****************************************************************/
10786
10787 WERROR _spoolss_65(struct pipes_struct *p,
10788                    struct spoolss_65 *r)
10789 {
10790         p->rng_fault_state = true;
10791         return WERR_NOT_SUPPORTED;
10792 }
10793
10794 /****************************************************************
10795  _spoolss_GetCorePrinterDrivers
10796 ****************************************************************/
10797
10798 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10799                                       struct spoolss_GetCorePrinterDrivers *r)
10800 {
10801         p->rng_fault_state = true;
10802         return WERR_NOT_SUPPORTED;
10803 }
10804
10805 /****************************************************************
10806  _spoolss_67
10807 ****************************************************************/
10808
10809 WERROR _spoolss_67(struct pipes_struct *p,
10810                    struct spoolss_67 *r)
10811 {
10812         p->rng_fault_state = true;
10813         return WERR_NOT_SUPPORTED;
10814 }
10815
10816 /****************************************************************
10817  _spoolss_GetPrinterDriverPackagePath
10818 ****************************************************************/
10819
10820 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10821                                             struct spoolss_GetPrinterDriverPackagePath *r)
10822 {
10823         p->rng_fault_state = true;
10824         return WERR_NOT_SUPPORTED;
10825 }
10826
10827 /****************************************************************
10828  _spoolss_69
10829 ****************************************************************/
10830
10831 WERROR _spoolss_69(struct pipes_struct *p,
10832                    struct spoolss_69 *r)
10833 {
10834         p->rng_fault_state = true;
10835         return WERR_NOT_SUPPORTED;
10836 }
10837
10838 /****************************************************************
10839  _spoolss_6a
10840 ****************************************************************/
10841
10842 WERROR _spoolss_6a(struct pipes_struct *p,
10843                    struct spoolss_6a *r)
10844 {
10845         p->rng_fault_state = true;
10846         return WERR_NOT_SUPPORTED;
10847 }
10848
10849 /****************************************************************
10850  _spoolss_6b
10851 ****************************************************************/
10852
10853 WERROR _spoolss_6b(struct pipes_struct *p,
10854                    struct spoolss_6b *r)
10855 {
10856         p->rng_fault_state = true;
10857         return WERR_NOT_SUPPORTED;
10858 }
10859
10860 /****************************************************************
10861  _spoolss_6c
10862 ****************************************************************/
10863
10864 WERROR _spoolss_6c(struct pipes_struct *p,
10865                    struct spoolss_6c *r)
10866 {
10867         p->rng_fault_state = true;
10868         return WERR_NOT_SUPPORTED;
10869 }
10870
10871 /****************************************************************
10872  _spoolss_6d
10873 ****************************************************************/
10874
10875 WERROR _spoolss_6d(struct pipes_struct *p,
10876                    struct spoolss_6d *r)
10877 {
10878         p->rng_fault_state = true;
10879         return WERR_NOT_SUPPORTED;
10880 }