1a9111c8a55e77fa4c3afb13a67bce3975b1001c
[kai/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                 prn_hnd->notify.cli_chan = NULL;
292         }
293 }
294
295 /****************************************************************************
296  Functions to free a printer entry datastruct.
297 ****************************************************************************/
298
299 static int printer_entry_destructor(struct printer_handle *Printer)
300 {
301         if (Printer->notify.cli_chan != NULL &&
302             Printer->notify.cli_chan->active_connections > 0) {
303                 int snum = -1;
304
305                 switch(Printer->printer_type) {
306                 case SPLHND_SERVER:
307                         srv_spoolss_replycloseprinter(snum, Printer);
308                         break;
309
310                 case SPLHND_PRINTER:
311                         snum = print_queue_snum(Printer->sharename);
312                         if (snum != -1) {
313                                 srv_spoolss_replycloseprinter(snum, Printer);
314                         }
315                         break;
316                 default:
317                         break;
318                 }
319         }
320
321         Printer->notify.flags=0;
322         Printer->notify.options=0;
323         Printer->notify.localmachine[0]='\0';
324         Printer->notify.printerlocal=0;
325         TALLOC_FREE(Printer->notify.option);
326         TALLOC_FREE(Printer->devmode);
327
328         /* Remove from the internal list. */
329         DLIST_REMOVE(printers_list, Printer);
330         return 0;
331 }
332
333 /****************************************************************************
334   find printer index by handle
335 ****************************************************************************/
336
337 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
338                                                         struct policy_handle *hnd)
339 {
340         struct printer_handle *find_printer = NULL;
341
342         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
343                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
344                 return NULL;
345         }
346
347         return find_printer;
348 }
349
350 /****************************************************************************
351  Close printer index by handle.
352 ****************************************************************************/
353
354 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
355 {
356         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
357
358         if (!Printer) {
359                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
360                         OUR_HANDLE(hnd)));
361                 return false;
362         }
363
364         close_policy_hnd(p, hnd);
365
366         return true;
367 }
368
369 /****************************************************************************
370  Delete a printer given a handle.
371 ****************************************************************************/
372
373 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
374                                   const char *sharename,
375                                   struct messaging_context *msg_ctx)
376 {
377         char *cmd = lp_deleteprinter_cmd();
378         char *command = NULL;
379         int ret;
380         bool is_print_op = false;
381
382         /* can't fail if we don't try */
383
384         if ( !*cmd )
385                 return WERR_OK;
386
387         command = talloc_asprintf(ctx,
388                         "%s \"%s\"",
389                         cmd, sharename);
390         if (!command) {
391                 return WERR_NOMEM;
392         }
393         if ( token )
394                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
395
396         DEBUG(10,("Running [%s]\n", command));
397
398         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
399
400         if ( is_print_op )
401                 become_root();
402
403         if ( (ret = smbrun(command, NULL)) == 0 ) {
404                 /* Tell everyone we updated smb.conf. */
405                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
406         }
407
408         if ( is_print_op )
409                 unbecome_root();
410
411         /********** END SePrintOperatorPrivlege BLOCK **********/
412
413         DEBUGADD(10,("returned [%d]\n", ret));
414
415         TALLOC_FREE(command);
416
417         if (ret != 0)
418                 return WERR_BADFID; /* What to return here? */
419
420         /* go ahead and re-read the services immediately */
421         become_root();
422         reload_services(msg_ctx, -1, false);
423         unbecome_root();
424
425         if ( lp_servicenumber( sharename ) >= 0 )
426                 return WERR_ACCESS_DENIED;
427
428         return WERR_OK;
429 }
430
431 /****************************************************************************
432  Delete a printer given a handle.
433 ****************************************************************************/
434
435 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
436 {
437         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
438         WERROR result;
439
440         if (!Printer) {
441                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
442                         OUR_HANDLE(hnd)));
443                 return WERR_BADFID;
444         }
445
446         /*
447          * It turns out that Windows allows delete printer on a handle
448          * opened by an admin user, then used on a pipe handle created
449          * by an anonymous user..... but they're working on security.... riiight !
450          * JRA.
451          */
452
453         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
454                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
455                 return WERR_ACCESS_DENIED;
456         }
457
458         /* this does not need a become root since the access check has been
459            done on the handle already */
460
461         result = winreg_delete_printer_key_internal(p->mem_ctx,
462                                            get_session_info_system(),
463                                            p->msg_ctx,
464                                            Printer->sharename,
465                                            "");
466         if (!W_ERROR_IS_OK(result)) {
467                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
468                 return WERR_BADFID;
469         }
470
471         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
472                                      Printer->sharename, p->msg_ctx);
473         if (!W_ERROR_IS_OK(result)) {
474                 return result;
475         }
476         prune_printername_cache();
477         return WERR_OK;
478 }
479
480 /****************************************************************************
481  Return the snum of a printer corresponding to an handle.
482 ****************************************************************************/
483
484 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
485                              int *number, struct share_params **params)
486 {
487         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
488
489         if (!Printer) {
490                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
491                         OUR_HANDLE(hnd)));
492                 return false;
493         }
494
495         switch (Printer->printer_type) {
496                 case SPLHND_PRINTER:
497                         DEBUG(4,("short name:%s\n", Printer->sharename));
498                         *number = print_queue_snum(Printer->sharename);
499                         return (*number != -1);
500                 case SPLHND_SERVER:
501                         return false;
502                 default:
503                         return false;
504         }
505 }
506
507 /****************************************************************************
508  Set printer handle type.
509  Check if it's \\server or \\server\printer
510 ****************************************************************************/
511
512 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
513 {
514         DEBUG(3,("Setting printer type=%s\n", handlename));
515
516         /* it's a print server */
517         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
518                 DEBUGADD(4,("Printer is a print server\n"));
519                 Printer->printer_type = SPLHND_SERVER;
520         }
521         /* it's a printer (set_printer_hnd_name() will handle port monitors */
522         else {
523                 DEBUGADD(4,("Printer is a printer\n"));
524                 Printer->printer_type = SPLHND_PRINTER;
525         }
526
527         return true;
528 }
529
530 static void prune_printername_cache_fn(const char *key, const char *value,
531                                        time_t timeout, void *private_data)
532 {
533         gencache_del(key);
534 }
535
536 static void prune_printername_cache(void)
537 {
538         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
539 }
540
541 /****************************************************************************
542  Set printer handle name..  Accept names like \\server, \\server\printer,
543  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
544  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
545  XcvDataPort() interface.
546 ****************************************************************************/
547
548 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
549                                    const struct auth_session_info *session_info,
550                                    struct messaging_context *msg_ctx,
551                                    struct printer_handle *Printer,
552                                    const char *handlename)
553 {
554         int snum;
555         int n_services=lp_numservices();
556         char *aprinter;
557         const char *printername;
558         const char *servername = NULL;
559         fstring sname;
560         bool found = false;
561         struct spoolss_PrinterInfo2 *info2 = NULL;
562         WERROR result;
563         char *p;
564
565         /*
566          * Hopefully nobody names his printers like this. Maybe \ or ,
567          * are illegal in printer names even?
568          */
569         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
570         char *cache_key;
571         char *tmp;
572
573         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
574                 (unsigned long)strlen(handlename)));
575
576         aprinter = discard_const_p(char, handlename);
577         if ( *handlename == '\\' ) {
578                 servername = canon_servername(handlename);
579                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
580                         *aprinter = '\0';
581                         aprinter++;
582                 }
583                 if (!is_myname_or_ipaddr(servername)) {
584                         return WERR_INVALID_PRINTER_NAME;
585                 }
586                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
587                 if (Printer->servername == NULL) {
588                         return WERR_NOMEM;
589                 }
590         }
591
592         if (Printer->printer_type == SPLHND_SERVER) {
593                 return WERR_OK;
594         }
595
596         if (Printer->printer_type != SPLHND_PRINTER) {
597                 return WERR_INVALID_HANDLE;
598         }
599
600         DEBUGADD(5, ("searching for [%s]\n", aprinter));
601
602         p = strchr(aprinter, ',');
603         if (p != NULL) {
604                 char *p2 = p;
605                 p++;
606                 if (*p == ' ') {
607                         p++;
608                 }
609                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
610                         *p2 = '\0';
611                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
612                         *p2 = '\0';
613                 }
614         }
615
616         if (p) {
617                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
618         }
619
620         /* check for the Port Monitor Interface */
621         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
622                 Printer->printer_type = SPLHND_PORTMON_TCP;
623                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
624                 found = true;
625         }
626         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
627                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
628                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
629                 found = true;
630         }
631
632         /*
633          * With hundreds of printers, the "for" loop iterating all
634          * shares can be quite expensive, as it is done on every
635          * OpenPrinter. The loop maps "aprinter" to "sname", the
636          * result of which we cache in gencache.
637          */
638
639         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
640                                     aprinter);
641         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
642
643                 found = (strcmp(tmp, printer_not_found) != 0);
644                 if (!found) {
645                         DEBUG(4, ("Printer %s not found\n", aprinter));
646                         SAFE_FREE(tmp);
647                         return WERR_INVALID_PRINTER_NAME;
648                 }
649                 fstrcpy(sname, tmp);
650                 SAFE_FREE(tmp);
651         }
652
653         /* Search all sharenames first as this is easier than pulling
654            the printer_info_2 off of disk. Don't use find_service() since
655            that calls out to map_username() */
656
657         /* do another loop to look for printernames */
658         for (snum = 0; !found && snum < n_services; snum++) {
659                 const char *printer = lp_const_servicename(snum);
660
661                 /* no point going on if this is not a printer */
662                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
663                         continue;
664                 }
665
666                 /* ignore [printers] share */
667                 if (strequal(printer, "printers")) {
668                         continue;
669                 }
670
671                 fstrcpy(sname, printer);
672                 if (strequal(aprinter, printer)) {
673                         found = true;
674                         break;
675                 }
676
677                 /* no point looking up the printer object if
678                    we aren't allowing printername != sharename */
679                 if (lp_force_printername(snum)) {
680                         continue;
681                 }
682
683                 result = winreg_get_printer_internal(mem_ctx,
684                                             session_info,
685                                             msg_ctx,
686                                             sname,
687                                             &info2);
688                 if ( !W_ERROR_IS_OK(result) ) {
689                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
690                                  sname, win_errstr(result)));
691                         continue;
692                 }
693
694                 printername = strrchr(info2->printername, '\\');
695                 if (printername == NULL) {
696                         printername = info2->printername;
697                 } else {
698                         printername++;
699                 }
700
701                 if (strequal(printername, aprinter)) {
702                         found = true;
703                         break;
704                 }
705
706                 DEBUGADD(10, ("printername: %s\n", printername));
707
708                 TALLOC_FREE(info2);
709         }
710
711         if ( !found ) {
712                 if (cache_key != NULL) {
713                         gencache_set(cache_key, printer_not_found,
714                                      time(NULL)+300);
715                         TALLOC_FREE(cache_key);
716                 }
717                 DEBUGADD(4,("Printer not found\n"));
718                 return WERR_INVALID_PRINTER_NAME;
719         }
720
721         if (cache_key != NULL) {
722                 gencache_set(cache_key, sname, time(NULL)+300);
723                 TALLOC_FREE(cache_key);
724         }
725
726         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
727
728         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
729
730         return WERR_OK;
731 }
732
733 /****************************************************************************
734  Find first available printer slot. creates a printer handle for you.
735  ****************************************************************************/
736
737 static WERROR open_printer_hnd(struct pipes_struct *p,
738                                struct policy_handle *hnd,
739                                const char *name,
740                                uint32_t access_granted)
741 {
742         struct printer_handle *new_printer;
743         WERROR result;
744
745         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
746
747         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
748         if (new_printer == NULL) {
749                 return WERR_NOMEM;
750         }
751         talloc_set_destructor(new_printer, printer_entry_destructor);
752
753         /* This also steals the printer_handle on the policy_handle */
754         if (!create_policy_hnd(p, hnd, new_printer)) {
755                 TALLOC_FREE(new_printer);
756                 return WERR_INVALID_HANDLE;
757         }
758
759         /* Add to the internal list. */
760         DLIST_ADD(printers_list, new_printer);
761
762         new_printer->notify.option=NULL;
763
764         if (!set_printer_hnd_printertype(new_printer, name)) {
765                 close_printer_handle(p, hnd);
766                 return WERR_INVALID_HANDLE;
767         }
768
769         result = set_printer_hnd_name(p->mem_ctx,
770                                       get_session_info_system(),
771                                       p->msg_ctx,
772                                       new_printer, name);
773         if (!W_ERROR_IS_OK(result)) {
774                 close_printer_handle(p, hnd);
775                 return result;
776         }
777
778         new_printer->access_granted = access_granted;
779
780         DEBUG(5, ("%d printer handles active\n",
781                   (int)num_pipe_handles(p)));
782
783         return WERR_OK;
784 }
785
786 /***************************************************************************
787  check to see if the client motify handle is monitoring the notification
788  given by (notify_type, notify_field).
789  **************************************************************************/
790
791 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
792                                       uint16_t notify_field)
793 {
794         return true;
795 }
796
797 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
798                                 uint16_t notify_field)
799 {
800         struct spoolss_NotifyOption *option = p->notify.option;
801         uint32_t i, j;
802
803         /*
804          * Flags should always be zero when the change notify
805          * is registered by the client's spooler.  A user Win32 app
806          * might use the flags though instead of the NOTIFY_OPTION_INFO
807          * --jerry
808          */
809
810         if (!option) {
811                 return false;
812         }
813
814         if (p->notify.flags)
815                 return is_monitoring_event_flags(
816                         p->notify.flags, notify_type, notify_field);
817
818         for (i = 0; i < option->count; i++) {
819
820                 /* Check match for notify_type */
821
822                 if (option->types[i].type != notify_type)
823                         continue;
824
825                 /* Check match for field */
826
827                 for (j = 0; j < option->types[i].count; j++) {
828                         if (option->types[i].fields[j].field == notify_field) {
829                                 return true;
830                         }
831                 }
832         }
833
834         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
835                    p->servername, p->sharename, notify_type, notify_field));
836
837         return false;
838 }
839
840 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
841         _data->data.integer[0] = _integer; \
842         _data->data.integer[1] = 0;
843
844
845 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
846         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
847         if (!_data->data.string.string) {\
848                 _data->data.string.size = 0; \
849         } \
850         _data->data.string.size = strlen_m_term(_p) * 2;
851
852 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
853         _data->data.devmode.devmode = _devmode;
854
855 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
856         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
857         if (!_data->data.sd.sd) { \
858                 _data->data.sd.sd_size = 0; \
859         } \
860         _data->data.sd.sd_size = \
861                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
862
863 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
864                                    struct tm *t,
865                                    const char **pp,
866                                    uint32_t *plen)
867 {
868         struct spoolss_Time st;
869         uint32_t len = 16;
870         char *p;
871
872         if (!init_systemtime(&st, t)) {
873                 return;
874         }
875
876         p = talloc_array(mem_ctx, char, len);
877         if (!p) {
878                 return;
879         }
880
881         /*
882          * Systemtime must be linearized as a set of UINT16's.
883          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
884          */
885
886         SSVAL(p, 0, st.year);
887         SSVAL(p, 2, st.month);
888         SSVAL(p, 4, st.day_of_week);
889         SSVAL(p, 6, st.day);
890         SSVAL(p, 8, st.hour);
891         SSVAL(p, 10, st.minute);
892         SSVAL(p, 12, st.second);
893         SSVAL(p, 14, st.millisecond);
894
895         *pp = p;
896         *plen = len;
897 }
898
899 /* Convert a notification message to a struct spoolss_Notify */
900
901 static void notify_one_value(struct spoolss_notify_msg *msg,
902                              struct spoolss_Notify *data,
903                              TALLOC_CTX *mem_ctx)
904 {
905         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
906 }
907
908 static void notify_string(struct spoolss_notify_msg *msg,
909                           struct spoolss_Notify *data,
910                           TALLOC_CTX *mem_ctx)
911 {
912         /* The length of the message includes the trailing \0 */
913
914         data->data.string.size = msg->len * 2;
915         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
916         if (!data->data.string.string) {
917                 data->data.string.size = 0;
918                 return;
919         }
920 }
921
922 static void notify_system_time(struct spoolss_notify_msg *msg,
923                                struct spoolss_Notify *data,
924                                TALLOC_CTX *mem_ctx)
925 {
926         data->data.string.string = NULL;
927         data->data.string.size = 0;
928
929         if (msg->len != sizeof(time_t)) {
930                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
931                           msg->len));
932                 return;
933         }
934
935         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
936                                &data->data.string.string,
937                                &data->data.string.size);
938 }
939
940 struct notify2_message_table {
941         const char *name;
942         void (*fn)(struct spoolss_notify_msg *msg,
943                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
944 };
945
946 static struct notify2_message_table printer_notify_table[] = {
947         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
948         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
949         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
950         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
951         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
952         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
953         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
954         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
955         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
956         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
957         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
958         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
959         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
960         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
961         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
962         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
963         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
964         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
965         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
966 };
967
968 static struct notify2_message_table job_notify_table[] = {
969         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
970         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
971         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
972         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
973         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
974         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
975         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
976         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
977         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
978         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
979         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
980         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
981         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
982         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
983         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
984         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
985         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
986         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
987         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
988         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
989         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
990         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
991         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
992         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
993 };
994
995
996 /***********************************************************************
997  Allocate talloc context for container object
998  **********************************************************************/
999
1000 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1001 {
1002         if ( !ctr )
1003                 return;
1004
1005         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1006
1007         return;
1008 }
1009
1010 /***********************************************************************
1011  release all allocated memory and zero out structure
1012  **********************************************************************/
1013
1014 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1015 {
1016         if ( !ctr )
1017                 return;
1018
1019         if ( ctr->ctx )
1020                 talloc_destroy(ctr->ctx);
1021
1022         ZERO_STRUCTP(ctr);
1023
1024         return;
1025 }
1026
1027 /***********************************************************************
1028  **********************************************************************/
1029
1030 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1031 {
1032         if ( !ctr )
1033                 return NULL;
1034
1035         return ctr->ctx;
1036 }
1037
1038 /***********************************************************************
1039  **********************************************************************/
1040
1041 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1042 {
1043         if ( !ctr || !ctr->msg_groups )
1044                 return NULL;
1045
1046         if ( idx >= ctr->num_groups )
1047                 return NULL;
1048
1049         return &ctr->msg_groups[idx];
1050
1051 }
1052
1053 /***********************************************************************
1054  How many groups of change messages do we have ?
1055  **********************************************************************/
1056
1057 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1058 {
1059         if ( !ctr )
1060                 return 0;
1061
1062         return ctr->num_groups;
1063 }
1064
1065 /***********************************************************************
1066  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1067  **********************************************************************/
1068
1069 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1070 {
1071         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1072         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1073         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1074         int                             i, new_slot;
1075
1076         if ( !ctr || !msg )
1077                 return 0;
1078
1079         /* loop over all groups looking for a matching printer name */
1080
1081         for ( i=0; i<ctr->num_groups; i++ ) {
1082                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1083                         break;
1084         }
1085
1086         /* add a new group? */
1087
1088         if ( i == ctr->num_groups ) {
1089                 ctr->num_groups++;
1090
1091                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1092                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1093                         return 0;
1094                 }
1095                 ctr->msg_groups = groups;
1096
1097                 /* clear the new entry and set the printer name */
1098
1099                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1100                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1101         }
1102
1103         /* add the change messages; 'i' is the correct index now regardless */
1104
1105         msg_grp = &ctr->msg_groups[i];
1106
1107         msg_grp->num_msgs++;
1108
1109         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1110                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1111                 return 0;
1112         }
1113         msg_grp->msgs = msg_list;
1114
1115         new_slot = msg_grp->num_msgs-1;
1116         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1117
1118         /* need to allocate own copy of data */
1119
1120         if ( msg->len != 0 )
1121                 msg_grp->msgs[new_slot].notify.data = (char *)
1122                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1123
1124         return ctr->num_groups;
1125 }
1126
1127 static void construct_info_data(struct spoolss_Notify *info_data,
1128                                 enum spoolss_NotifyType type,
1129                                 uint16_t field, int id);
1130
1131 /***********************************************************************
1132  Send a change notication message on all handles which have a call
1133  back registered
1134  **********************************************************************/
1135
1136 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1137                                   struct printer_handle *prn_hnd,
1138                                   SPOOLSS_NOTIFY_MSG *messages,
1139                                   uint32_t num_msgs,
1140                                   struct spoolss_Notify **_notifies,
1141                                   int *_count)
1142 {
1143         struct spoolss_Notify *notifies;
1144         SPOOLSS_NOTIFY_MSG *msg;
1145         int count = 0;
1146         uint32_t id;
1147         int i;
1148
1149         notifies = talloc_zero_array(mem_ctx,
1150                                      struct spoolss_Notify, num_msgs);
1151         if (!notifies) {
1152                 return ENOMEM;
1153         }
1154
1155         for (i = 0; i < num_msgs; i++) {
1156
1157                 msg = &messages[i];
1158
1159                 /* Are we monitoring this event? */
1160
1161                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1162                         continue;
1163                 }
1164
1165                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1166                            "for printer [%s]\n",
1167                            msg->type, msg->field, prn_hnd->sharename));
1168
1169                 /*
1170                  * if the is a printer notification handle and not a job
1171                  * notification type, then set the id to 0.
1172                  * Otherwise just use what was specified in the message.
1173                  *
1174                  * When registering change notification on a print server
1175                  * handle we always need to send back the id (snum) matching
1176                  * the printer for which the change took place.
1177                  * For change notify registered on a printer handle,
1178                  * this does not matter and the id should be 0.
1179                  *
1180                  * --jerry
1181                  */
1182
1183                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1184                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1185                         id = 0;
1186                 } else {
1187                         id = msg->id;
1188                 }
1189
1190                 /* Convert unix jobid to smb jobid */
1191
1192                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1193                         id = sysjob_to_jobid(msg->id);
1194
1195                         if (id == -1) {
1196                                 DEBUG(3, ("no such unix jobid %d\n",
1197                                           msg->id));
1198                                 continue;
1199                         }
1200                 }
1201
1202                 construct_info_data(&notifies[count],
1203                                     msg->type, msg->field, id);
1204
1205                 switch(msg->type) {
1206                 case PRINTER_NOTIFY_TYPE:
1207                         if (printer_notify_table[msg->field].fn) {
1208                                 printer_notify_table[msg->field].fn(msg,
1209                                                 &notifies[count], mem_ctx);
1210                         }
1211                         break;
1212
1213                 case JOB_NOTIFY_TYPE:
1214                         if (job_notify_table[msg->field].fn) {
1215                                 job_notify_table[msg->field].fn(msg,
1216                                                 &notifies[count], mem_ctx);
1217                         }
1218                         break;
1219
1220                 default:
1221                         DEBUG(5, ("Unknown notification type %d\n",
1222                                   msg->type));
1223                         continue;
1224                 }
1225
1226                 count++;
1227         }
1228
1229         *_notifies = notifies;
1230         *_count = count;
1231
1232         return 0;
1233 }
1234
1235 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1236                                 struct printer_handle *prn_hnd,
1237                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1238 {
1239         struct spoolss_Notify *notifies;
1240         int count = 0;
1241         union spoolss_ReplyPrinterInfo info;
1242         struct spoolss_NotifyInfo info0;
1243         uint32_t reply_result;
1244         NTSTATUS status;
1245         WERROR werr;
1246         int ret;
1247
1248         /* Is there notification on this handle? */
1249         if (prn_hnd->notify.cli_chan == NULL ||
1250             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1251             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1252             prn_hnd->notify.cli_chan->active_connections == 0) {
1253                 return 0;
1254         }
1255
1256         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1257                    prn_hnd->servername, prn_hnd->sharename));
1258
1259         /* For this printer? Print servers always receive notifications. */
1260         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1261             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1262                 return 0;
1263         }
1264
1265         DEBUG(10,("Our printer\n"));
1266
1267         /* build the array of change notifications */
1268         ret = build_notify2_messages(mem_ctx, prn_hnd,
1269                                      msg_group->msgs,
1270                                      msg_group->num_msgs,
1271                                      &notifies, &count);
1272         if (ret) {
1273                 return ret;
1274         }
1275
1276         info0.version   = 0x2;
1277         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1278         info0.count     = count;
1279         info0.notifies  = notifies;
1280
1281         info.info0 = &info0;
1282
1283         status = dcerpc_spoolss_RouterReplyPrinterEx(
1284                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1285                                 mem_ctx,
1286                                 &prn_hnd->notify.cli_hnd,
1287                                 prn_hnd->notify.change, /* color */
1288                                 prn_hnd->notify.flags,
1289                                 &reply_result,
1290                                 0, /* reply_type, must be 0 */
1291                                 info, &werr);
1292         if (!NT_STATUS_IS_OK(status)) {
1293                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1294                           "failed: %s\n",
1295                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1296                           nt_errstr(status)));
1297                 werr = ntstatus_to_werror(status);
1298         } else if (!W_ERROR_IS_OK(werr)) {
1299                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1300                           "failed: %s\n",
1301                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1302                           win_errstr(werr)));
1303         }
1304         switch (reply_result) {
1305         case 0:
1306                 break;
1307         case PRINTER_NOTIFY_INFO_DISCARDED:
1308         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1309         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1310                 break;
1311         default:
1312                 break;
1313         }
1314
1315         return 0;
1316 }
1317
1318 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1319 {
1320         struct printer_handle    *p;
1321         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1322         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1323         int ret;
1324
1325         if ( !msg_group ) {
1326                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1327                 return;
1328         }
1329
1330         if (!msg_group->msgs) {
1331                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1332                 return;
1333         }
1334
1335         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1336
1337         /* loop over all printers */
1338
1339         for (p = printers_list; p; p = p->next) {
1340                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1341                 if (ret) {
1342                         goto done;
1343                 }
1344         }
1345
1346 done:
1347         DEBUG(8,("send_notify2_changes: Exit...\n"));
1348         return;
1349 }
1350
1351 /***********************************************************************
1352  **********************************************************************/
1353
1354 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1355 {
1356
1357         uint32_t tv_sec, tv_usec;
1358         size_t offset = 0;
1359
1360         /* Unpack message */
1361
1362         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1363                              msg->printer);
1364
1365         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1366                                 &tv_sec, &tv_usec,
1367                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1368
1369         if (msg->len == 0)
1370                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1371                            &msg->notify.value[0], &msg->notify.value[1]);
1372         else
1373                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1374                            &msg->len, &msg->notify.data);
1375
1376         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1377                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1378
1379         tv->tv_sec = tv_sec;
1380         tv->tv_usec = tv_usec;
1381
1382         if (msg->len == 0)
1383                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1384                           msg->notify.value[1]));
1385         else
1386                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1387
1388         return true;
1389 }
1390
1391 /********************************************************************
1392  Receive a notify2 message list
1393  ********************************************************************/
1394
1395 static void receive_notify2_message_list(struct messaging_context *msg,
1396                                          void *private_data,
1397                                          uint32_t msg_type,
1398                                          struct server_id server_id,
1399                                          DATA_BLOB *data)
1400 {
1401         size_t                  msg_count, i;
1402         char                    *buf = (char *)data->data;
1403         char                    *msg_ptr;
1404         size_t                  msg_len;
1405         SPOOLSS_NOTIFY_MSG      notify;
1406         SPOOLSS_NOTIFY_MSG_CTR  messages;
1407         int                     num_groups;
1408
1409         if (data->length < 4) {
1410                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1411                 return;
1412         }
1413
1414         msg_count = IVAL(buf, 0);
1415         msg_ptr = buf + 4;
1416
1417         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1418
1419         if (msg_count == 0) {
1420                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1421                 return;
1422         }
1423
1424         /* initialize the container */
1425
1426         ZERO_STRUCT( messages );
1427         notify_msg_ctr_init( &messages );
1428
1429         /*
1430          * build message groups for each printer identified
1431          * in a change_notify msg.  Remember that a PCN message
1432          * includes the handle returned for the srv_spoolss_replyopenprinter()
1433          * call.  Therefore messages are grouped according to printer handle.
1434          */
1435
1436         for ( i=0; i<msg_count; i++ ) {
1437                 struct timeval msg_tv;
1438
1439                 if (msg_ptr + 4 - buf > data->length) {
1440                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1441                         return;
1442                 }
1443
1444                 msg_len = IVAL(msg_ptr,0);
1445                 msg_ptr += 4;
1446
1447                 if (msg_ptr + msg_len - buf > data->length) {
1448                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1449                         return;
1450                 }
1451
1452                 /* unpack messages */
1453
1454                 ZERO_STRUCT( notify );
1455                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1456                 msg_ptr += msg_len;
1457
1458                 /* add to correct list in container */
1459
1460                 notify_msg_ctr_addmsg( &messages, &notify );
1461
1462                 /* free memory that might have been allocated by notify2_unpack_msg() */
1463
1464                 if ( notify.len != 0 )
1465                         SAFE_FREE( notify.notify.data );
1466         }
1467
1468         /* process each group of messages */
1469
1470         num_groups = notify_msg_ctr_numgroups( &messages );
1471         for ( i=0; i<num_groups; i++ )
1472                 send_notify2_changes( &messages, i );
1473
1474
1475         /* cleanup */
1476
1477         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1478                 (uint32_t)msg_count ));
1479
1480         notify_msg_ctr_destroy( &messages );
1481
1482         return;
1483 }
1484
1485 /********************************************************************
1486  Send a message to ourself about new driver being installed
1487  so we can upgrade the information for each printer bound to this
1488  driver
1489  ********************************************************************/
1490
1491 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1492                                             struct messaging_context *msg_ctx)
1493 {
1494         int len = strlen(drivername);
1495
1496         if (!len)
1497                 return false;
1498
1499         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1500                 drivername));
1501
1502         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1503                            MSG_PRINTER_DRVUPGRADE,
1504                            (const uint8_t *)drivername, len+1);
1505
1506         return true;
1507 }
1508
1509 void srv_spoolss_cleanup(void)
1510 {
1511         struct printer_session_counter *session_counter;
1512
1513         for (session_counter = counter_list;
1514              session_counter != NULL;
1515              session_counter = counter_list) {
1516                 DLIST_REMOVE(counter_list, session_counter);
1517                 TALLOC_FREE(session_counter);
1518         }
1519 }
1520
1521 /**********************************************************************
1522  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1523  over all printers, upgrading ones as necessary
1524  **********************************************************************/
1525
1526 void do_drv_upgrade_printer(struct messaging_context *msg,
1527                             void *private_data,
1528                             uint32_t msg_type,
1529                             struct server_id server_id,
1530                             DATA_BLOB *data)
1531 {
1532         TALLOC_CTX *tmp_ctx;
1533         const struct auth_session_info *session_info = get_session_info_system();
1534         struct spoolss_PrinterInfo2 *pinfo2;
1535         WERROR result;
1536         const char *drivername;
1537         int snum;
1538         int n_services = lp_numservices();
1539         struct dcerpc_binding_handle *b = NULL;
1540
1541         tmp_ctx = talloc_new(NULL);
1542         if (!tmp_ctx) return;
1543
1544         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1545         if (!drivername) {
1546                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1547                 goto done;
1548         }
1549
1550         DEBUG(10, ("do_drv_upgrade_printer: "
1551                    "Got message for new driver [%s]\n", drivername));
1552
1553         /* Iterate the printer list */
1554
1555         for (snum = 0; snum < n_services; snum++) {
1556                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1557                         continue;
1558                 }
1559
1560                 /* ignore [printers] share */
1561                 if (strequal(lp_const_servicename(snum), "printers")) {
1562                         continue;
1563                 }
1564
1565                 if (b == NULL) {
1566                         result = winreg_printer_binding_handle(tmp_ctx,
1567                                                                session_info,
1568                                                                msg,
1569                                                                &b);
1570                         if (!W_ERROR_IS_OK(result)) {
1571                                 break;
1572                         }
1573                 }
1574
1575                 result = winreg_get_printer(tmp_ctx, b,
1576                                             lp_const_servicename(snum),
1577                                             &pinfo2);
1578
1579                 if (!W_ERROR_IS_OK(result)) {
1580                         continue;
1581                 }
1582
1583                 if (!pinfo2->drivername) {
1584                         continue;
1585                 }
1586
1587                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1588                         continue;
1589                 }
1590
1591                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1592
1593                 /* all we care about currently is the change_id */
1594                 result = winreg_printer_update_changeid(tmp_ctx, b,
1595                                                         pinfo2->printername);
1596
1597                 if (!W_ERROR_IS_OK(result)) {
1598                         DEBUG(3, ("do_drv_upgrade_printer: "
1599                                   "Failed to update changeid [%s]\n",
1600                                   win_errstr(result)));
1601                 }
1602         }
1603
1604         /* all done */
1605 done:
1606         talloc_free(tmp_ctx);
1607 }
1608
1609 /********************************************************************
1610  Update the cache for all printq's with a registered client
1611  connection
1612  ********************************************************************/
1613
1614 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1615 {
1616         struct printer_handle *printer = printers_list;
1617         int snum;
1618
1619         /* loop through all printers and update the cache where
1620            a client is connected */
1621         while (printer) {
1622                 if ((printer->printer_type == SPLHND_PRINTER) &&
1623                     ((printer->notify.cli_chan != NULL) &&
1624                      (printer->notify.cli_chan->active_connections > 0))) {
1625                         snum = print_queue_snum(printer->sharename);
1626                         print_queue_status(msg_ctx, snum, NULL, NULL);
1627                 }
1628
1629                 printer = printer->next;
1630         }
1631
1632         return;
1633 }
1634
1635 /****************************************************************
1636  _spoolss_OpenPrinter
1637 ****************************************************************/
1638
1639 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1640                             struct spoolss_OpenPrinter *r)
1641 {
1642         struct spoolss_OpenPrinterEx e;
1643         WERROR werr;
1644
1645         ZERO_STRUCT(e.in.userlevel);
1646
1647         e.in.printername        = r->in.printername;
1648         e.in.datatype           = r->in.datatype;
1649         e.in.devmode_ctr        = r->in.devmode_ctr;
1650         e.in.access_mask        = r->in.access_mask;
1651         e.in.level              = 0;
1652
1653         e.out.handle            = r->out.handle;
1654
1655         werr = _spoolss_OpenPrinterEx(p, &e);
1656
1657         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1658                 /* OpenPrinterEx returns this for a bad
1659                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1660                  * instead.
1661                  */
1662                 werr = WERR_INVALID_PRINTER_NAME;
1663         }
1664
1665         return werr;
1666 }
1667
1668 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1669                               struct spoolss_DeviceMode *orig,
1670                               struct spoolss_DeviceMode **dest)
1671 {
1672         struct spoolss_DeviceMode *dm;
1673
1674         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1675         if (!dm) {
1676                 return WERR_NOMEM;
1677         }
1678
1679         /* copy all values, then duplicate strings and structs */
1680         *dm = *orig;
1681
1682         dm->devicename = talloc_strdup(dm, orig->devicename);
1683         if (!dm->devicename) {
1684                 return WERR_NOMEM;
1685         }
1686         dm->formname = talloc_strdup(dm, orig->formname);
1687         if (!dm->formname) {
1688                 return WERR_NOMEM;
1689         }
1690         if (orig->driverextra_data.data) {
1691                 dm->driverextra_data.data =
1692                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1693                                         orig->driverextra_data.length);
1694                 if (!dm->driverextra_data.data) {
1695                         return WERR_NOMEM;
1696                 }
1697         }
1698
1699         *dest = dm;
1700         return WERR_OK;
1701 }
1702
1703 /****************************************************************
1704  _spoolss_OpenPrinterEx
1705 ****************************************************************/
1706
1707 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1708                               struct spoolss_OpenPrinterEx *r)
1709 {
1710         int snum;
1711         char *raddr;
1712         char *rhost;
1713         struct printer_handle *Printer=NULL;
1714         WERROR result;
1715         int rc;
1716
1717         if (!r->in.printername) {
1718                 return WERR_INVALID_PARAM;
1719         }
1720
1721         if (r->in.level > 3) {
1722                 return WERR_INVALID_PARAM;
1723         }
1724         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1725             (r->in.level == 2 && !r->in.userlevel.level2) ||
1726             (r->in.level == 3 && !r->in.userlevel.level3)) {
1727                 return WERR_INVALID_PARAM;
1728         }
1729
1730         /* some sanity check because you can open a printer or a print server */
1731         /* aka: \\server\printer or \\server */
1732
1733         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1734
1735         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1736         if (!W_ERROR_IS_OK(result)) {
1737                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1738                         "for printer %s\n", r->in.printername));
1739                 ZERO_STRUCTP(r->out.handle);
1740                 return result;
1741         }
1742
1743         Printer = find_printer_index_by_hnd(p, r->out.handle);
1744         if ( !Printer ) {
1745                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1746                         "handle we created for printer %s\n", r->in.printername));
1747                 close_printer_handle(p, r->out.handle);
1748                 ZERO_STRUCTP(r->out.handle);
1749                 return WERR_INVALID_PARAM;
1750         }
1751
1752         /*
1753          * First case: the user is opening the print server:
1754          *
1755          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1756          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1757          *
1758          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1759          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1760          * or if the user is listed in the smb.conf printer admin parameter.
1761          *
1762          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1763          * client view printer folder, but does not show the MSAPW.
1764          *
1765          * Note: this test needs code to check access rights here too. Jeremy
1766          * could you look at this?
1767          *
1768          * Second case: the user is opening a printer:
1769          * NT doesn't let us connect to a printer if the connecting user
1770          * doesn't have print permission.
1771          *
1772          * Third case: user is opening a Port Monitor
1773          * access checks same as opening a handle to the print server.
1774          */
1775
1776         switch (Printer->printer_type )
1777         {
1778         case SPLHND_SERVER:
1779         case SPLHND_PORTMON_TCP:
1780         case SPLHND_PORTMON_LOCAL:
1781                 /* Printserver handles use global struct... */
1782
1783                 snum = -1;
1784
1785                 /* Map standard access rights to object specific access rights */
1786
1787                 se_map_standard(&r->in.access_mask,
1788                                 &printserver_std_mapping);
1789
1790                 /* Deny any object specific bits that don't apply to print
1791                    servers (i.e printer and job specific bits) */
1792
1793                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1794
1795                 if (r->in.access_mask &
1796                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1797                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1798                         close_printer_handle(p, r->out.handle);
1799                         ZERO_STRUCTP(r->out.handle);
1800                         return WERR_ACCESS_DENIED;
1801                 }
1802
1803                 /* Allow admin access */
1804
1805                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1806                 {
1807                         if (!lp_ms_add_printer_wizard()) {
1808                                 close_printer_handle(p, r->out.handle);
1809                                 ZERO_STRUCTP(r->out.handle);
1810                                 return WERR_ACCESS_DENIED;
1811                         }
1812
1813                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1814                            and not a printer admin, then fail */
1815
1816                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1817                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1818                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1819                             !token_contains_name_in_list(
1820                                     uidtoname(p->session_info->unix_token->uid),
1821                                     p->session_info->info->domain_name,
1822                                     NULL,
1823                                     p->session_info->security_token,
1824                                     lp_printer_admin(snum))) {
1825                                 close_printer_handle(p, r->out.handle);
1826                                 ZERO_STRUCTP(r->out.handle);
1827                                 DEBUG(3,("access DENIED as user is not root, "
1828                                         "has no printoperator privilege, "
1829                                         "not a member of the printoperator builtin group and "
1830                                         "is not in printer admin list"));
1831                                 return WERR_ACCESS_DENIED;
1832                         }
1833
1834                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1835                 }
1836                 else
1837                 {
1838                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1839                 }
1840
1841                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1842                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1843
1844                 /* We fall through to return WERR_OK */
1845                 break;
1846
1847         case SPLHND_PRINTER:
1848                 /* NT doesn't let us connect to a printer if the connecting user
1849                    doesn't have print permission.  */
1850
1851                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1852                         close_printer_handle(p, r->out.handle);
1853                         ZERO_STRUCTP(r->out.handle);
1854                         return WERR_BADFID;
1855                 }
1856
1857                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1858                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1859                 }
1860
1861                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1862
1863                 /* map an empty access mask to the minimum access mask */
1864                 if (r->in.access_mask == 0x0)
1865                         r->in.access_mask = PRINTER_ACCESS_USE;
1866
1867                 /*
1868                  * If we are not serving the printer driver for this printer,
1869                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1870                  * will keep NT clients happy  --jerry
1871                  */
1872
1873                 if (lp_use_client_driver(snum)
1874                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1875                 {
1876                         r->in.access_mask = PRINTER_ACCESS_USE;
1877                 }
1878
1879                 /* check smb.conf parameters and the the sec_desc */
1880                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1881                                                          p->mem_ctx);
1882                 if (raddr == NULL) {
1883                         return WERR_NOMEM;
1884                 }
1885
1886                 rc = get_remote_hostname(p->remote_address,
1887                                          &rhost,
1888                                          p->mem_ctx);
1889                 if (rc < 0) {
1890                         return WERR_NOMEM;
1891                 }
1892                 if (strequal(rhost, "UNKNOWN")) {
1893                         rhost = raddr;
1894                 }
1895
1896                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1897                                   rhost, raddr)) {
1898                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1899                         ZERO_STRUCTP(r->out.handle);
1900                         return WERR_ACCESS_DENIED;
1901                 }
1902
1903                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1904                                    p->session_info->security_token, snum) ||
1905                     !print_access_check(p->session_info,
1906                                         p->msg_ctx,
1907                                         snum,
1908                                         r->in.access_mask)) {
1909                         DEBUG(3, ("access DENIED for printer open\n"));
1910                         close_printer_handle(p, r->out.handle);
1911                         ZERO_STRUCTP(r->out.handle);
1912                         return WERR_ACCESS_DENIED;
1913                 }
1914
1915                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1916                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1917                         close_printer_handle(p, r->out.handle);
1918                         ZERO_STRUCTP(r->out.handle);
1919                         return WERR_ACCESS_DENIED;
1920                 }
1921
1922                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1923                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1924                 else
1925                         r->in.access_mask = PRINTER_ACCESS_USE;
1926
1927                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1928                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1929
1930                 winreg_create_printer_internal(p->mem_ctx,
1931                                       get_session_info_system(),
1932                                       p->msg_ctx,
1933                                       lp_const_servicename(snum));
1934
1935                 break;
1936
1937         default:
1938                 /* sanity check to prevent programmer error */
1939                 ZERO_STRUCTP(r->out.handle);
1940                 return WERR_BADFID;
1941         }
1942
1943         Printer->access_granted = r->in.access_mask;
1944
1945         /*
1946          * If the client sent a devmode in the OpenPrinter() call, then
1947          * save it here in case we get a job submission on this handle
1948          */
1949
1950          if ((Printer->printer_type != SPLHND_SERVER) &&
1951              r->in.devmode_ctr.devmode) {
1952                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1953                                 &Printer->devmode);
1954          }
1955
1956 #if 0   /* JERRY -- I'm doubtful this is really effective */
1957         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1958            optimization in Windows 2000 clients  --jerry */
1959
1960         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1961                 && (RA_WIN2K == get_remote_arch()) )
1962         {
1963                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1964                 sys_usleep( 500000 );
1965         }
1966 #endif
1967
1968         return WERR_OK;
1969 }
1970
1971 /****************************************************************
1972  _spoolss_ClosePrinter
1973 ****************************************************************/
1974
1975 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1976                              struct spoolss_ClosePrinter *r)
1977 {
1978         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1979
1980         if (Printer && Printer->document_started) {
1981                 struct spoolss_EndDocPrinter e;
1982
1983                 e.in.handle = r->in.handle;
1984
1985                 _spoolss_EndDocPrinter(p, &e);
1986         }
1987
1988         if (!close_printer_handle(p, r->in.handle))
1989                 return WERR_BADFID;
1990
1991         /* clear the returned printer handle.  Observed behavior
1992            from Win2k server.  Don't think this really matters.
1993            Previous code just copied the value of the closed
1994            handle.    --jerry */
1995
1996         ZERO_STRUCTP(r->out.handle);
1997
1998         return WERR_OK;
1999 }
2000
2001 /****************************************************************
2002  _spoolss_DeletePrinter
2003 ****************************************************************/
2004
2005 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2006                               struct spoolss_DeletePrinter *r)
2007 {
2008         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2009         WERROR result;
2010         int snum;
2011
2012         if (Printer && Printer->document_started) {
2013                 struct spoolss_EndDocPrinter e;
2014
2015                 e.in.handle = r->in.handle;
2016
2017                 _spoolss_EndDocPrinter(p, &e);
2018         }
2019
2020         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2021                 winreg_delete_printer_key_internal(p->mem_ctx,
2022                                           get_session_info_system(),
2023                                           p->msg_ctx,
2024                                           lp_const_servicename(snum),
2025                                           "");
2026         }
2027
2028         result = delete_printer_handle(p, r->in.handle);
2029
2030         return result;
2031 }
2032
2033 /*******************************************************************
2034  * static function to lookup the version id corresponding to an
2035  * long architecture string
2036  ******************************************************************/
2037
2038 static const struct print_architecture_table_node archi_table[]= {
2039
2040         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2041         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2042         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2043         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2044         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2045         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2046         {"Windows x64",          SPL_ARCH_X64,          3 },
2047         {NULL,                   "",            -1 }
2048 };
2049
2050 static int get_version_id(const char *arch)
2051 {
2052         int i;
2053
2054         for (i=0; archi_table[i].long_archi != NULL; i++)
2055         {
2056                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2057                         return (archi_table[i].version);
2058         }
2059
2060         return -1;
2061 }
2062
2063 /****************************************************************
2064  _spoolss_DeletePrinterDriver
2065 ****************************************************************/
2066
2067 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2068                                     struct spoolss_DeletePrinterDriver *r)
2069 {
2070
2071         struct spoolss_DriverInfo8 *info = NULL;
2072         struct spoolss_DriverInfo8 *info_win2k = NULL;
2073         int                             version;
2074         WERROR                          status;
2075         struct dcerpc_binding_handle *b;
2076         TALLOC_CTX *tmp_ctx = NULL;
2077
2078         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2079            and not a printer admin, then fail */
2080
2081         if ( (p->session_info->unix_token->uid != sec_initial_uid())
2082              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2083                 && !token_contains_name_in_list(
2084                         uidtoname(p->session_info->unix_token->uid),
2085                         p->session_info->info->domain_name,
2086                         NULL,
2087                         p->session_info->security_token,
2088                         lp_printer_admin(-1)) )
2089         {
2090                 return WERR_ACCESS_DENIED;
2091         }
2092
2093         /* check that we have a valid driver name first */
2094
2095         if ((version = get_version_id(r->in.architecture)) == -1) {
2096                 return WERR_INVALID_ENVIRONMENT;
2097         }
2098
2099         tmp_ctx = talloc_new(p->mem_ctx);
2100         if (!tmp_ctx) {
2101                 return WERR_NOMEM;
2102         }
2103
2104         status = winreg_printer_binding_handle(tmp_ctx,
2105                                                get_session_info_system(),
2106                                                p->msg_ctx,
2107                                                &b);
2108         if (!W_ERROR_IS_OK(status)) {
2109                 goto done;
2110         }
2111
2112         status = winreg_get_driver(tmp_ctx, b,
2113                                    r->in.architecture, r->in.driver,
2114                                    version, &info);
2115         if (!W_ERROR_IS_OK(status)) {
2116                 /* try for Win2k driver if "Windows NT x86" */
2117
2118                 if ( version == 2 ) {
2119                         version = 3;
2120
2121                         status = winreg_get_driver(tmp_ctx, b,
2122                                                    r->in.architecture,
2123                                                    r->in.driver,
2124                                                    version, &info);
2125                         if (!W_ERROR_IS_OK(status)) {
2126                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2127                                 goto done;
2128                         }
2129                 }
2130                 /* otherwise it was a failure */
2131                 else {
2132                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2133                         goto done;
2134                 }
2135
2136         }
2137
2138         if (printer_driver_in_use(tmp_ctx,
2139                                   b,
2140                                   info)) {
2141                 status = WERR_PRINTER_DRIVER_IN_USE;
2142                 goto done;
2143         }
2144
2145         if (version == 2) {
2146                 status = winreg_get_driver(tmp_ctx, b,
2147                                            r->in.architecture,
2148                                            r->in.driver, 3, &info_win2k);
2149                 if (W_ERROR_IS_OK(status)) {
2150                         /* if we get to here, we now have 2 driver info structures to remove */
2151                         /* remove the Win2k driver first*/
2152
2153                         status = winreg_del_driver(tmp_ctx, b,
2154                                                    info_win2k, 3);
2155                         talloc_free(info_win2k);
2156
2157                         /* this should not have failed---if it did, report to client */
2158                         if (!W_ERROR_IS_OK(status)) {
2159                                 goto done;
2160                         }
2161                 }
2162         }
2163
2164         status = winreg_del_driver(tmp_ctx, b,
2165                                    info, version);
2166
2167 done:
2168         talloc_free(tmp_ctx);
2169
2170         return status;
2171 }
2172
2173 /****************************************************************
2174  _spoolss_DeletePrinterDriverEx
2175 ****************************************************************/
2176
2177 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2178                                       struct spoolss_DeletePrinterDriverEx *r)
2179 {
2180         struct spoolss_DriverInfo8      *info = NULL;
2181         struct spoolss_DriverInfo8      *info_win2k = NULL;
2182         int                             version;
2183         bool                            delete_files;
2184         WERROR                          status;
2185         struct dcerpc_binding_handle *b;
2186         TALLOC_CTX *tmp_ctx = NULL;
2187
2188         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2189            and not a printer admin, then fail */
2190
2191         if ( (p->session_info->unix_token->uid != sec_initial_uid())
2192                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2193                 && !token_contains_name_in_list(
2194                         uidtoname(p->session_info->unix_token->uid),
2195                         p->session_info->info->domain_name,
2196                         NULL,
2197                         p->session_info->security_token, lp_printer_admin(-1)) )
2198         {
2199                 return WERR_ACCESS_DENIED;
2200         }
2201
2202         /* check that we have a valid driver name first */
2203         if ((version = get_version_id(r->in.architecture)) == -1) {
2204                 /* this is what NT returns */
2205                 return WERR_INVALID_ENVIRONMENT;
2206         }
2207
2208         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) {
2209                 version = r->in.version;
2210         }
2211
2212         tmp_ctx = talloc_new(p->mem_ctx);
2213         if (!tmp_ctx) {
2214                 return WERR_NOMEM;
2215         }
2216
2217         status = winreg_printer_binding_handle(tmp_ctx,
2218                                                get_session_info_system(),
2219                                                p->msg_ctx,
2220                                                &b);
2221         if (!W_ERROR_IS_OK(status)) {
2222                 goto done;
2223         }
2224
2225         status = winreg_get_driver(tmp_ctx, b,
2226                                    r->in.architecture,
2227                                    r->in.driver,
2228                                    version,
2229                                    &info);
2230         if (!W_ERROR_IS_OK(status)) {
2231                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2232
2233                 /*
2234                  * if the client asked for a specific version,
2235                  * or this is something other than Windows NT x86,
2236                  * then we've failed
2237                  */
2238
2239                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2240                         goto done;
2241
2242                 /* try for Win2k driver if "Windows NT x86" */
2243
2244                 version = 3;
2245                 status = winreg_get_driver(tmp_ctx, b,
2246                                            r->in.architecture,
2247                                            r->in.driver,
2248                                            version, &info);
2249                 if (!W_ERROR_IS_OK(status)) {
2250                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2251                         goto done;
2252                 }
2253         }
2254
2255         if (printer_driver_in_use(tmp_ctx,
2256                                   b,
2257                                   info)) {
2258                 status = WERR_PRINTER_DRIVER_IN_USE;
2259                 goto done;
2260         }
2261
2262         /*
2263          * we have a couple of cases to consider.
2264          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2265          *     then the delete should fail if **any** files overlap with
2266          *     other drivers
2267          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2268          *     non-overlapping files
2269          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2270          *     is set, the do not delete any files
2271          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2272          */
2273
2274         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2275
2276         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2277
2278         if (delete_files &&
2279             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2280             printer_driver_files_in_use(tmp_ctx,
2281                                         b,
2282                                         info)) {
2283                 /* no idea of the correct error here */
2284                 status = WERR_ACCESS_DENIED;
2285                 goto done;
2286         }
2287
2288
2289         /* also check for W32X86/3 if necessary; maybe we already have? */
2290
2291         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2292                 status = winreg_get_driver(tmp_ctx, b,
2293                                            r->in.architecture,
2294                                            r->in.driver, 3, &info_win2k);
2295                 if (W_ERROR_IS_OK(status)) {
2296
2297                         if (delete_files &&
2298                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2299                             printer_driver_files_in_use(info,
2300                                                         b,
2301                                                         info_win2k)) {
2302                                 /* no idea of the correct error here */
2303                                 talloc_free(info_win2k);
2304                                 status = WERR_ACCESS_DENIED;
2305                                 goto done;
2306                         }
2307
2308                         /* if we get to here, we now have 2 driver info structures to remove */
2309                         /* remove the Win2k driver first*/
2310
2311                         status = winreg_del_driver(tmp_ctx, b,
2312                                                    info_win2k,
2313                                                    3);
2314
2315                         /* this should not have failed---if it did, report to client */
2316
2317                         if (!W_ERROR_IS_OK(status)) {
2318                                 goto done;
2319                         }
2320
2321                         /*
2322                          * now delete any associated files if delete_files is
2323                          * true. Even if this part failes, we return succes
2324                          * because the driver doesn not exist any more
2325                          */
2326                         if (delete_files) {
2327                                 delete_driver_files(get_session_info_system(),
2328                                                     info_win2k);
2329                         }
2330                 }
2331         }
2332
2333         status = winreg_del_driver(tmp_ctx, b,
2334                                    info,
2335                                    version);
2336         if (!W_ERROR_IS_OK(status)) {
2337                 goto done;
2338         }
2339
2340         /*
2341          * now delete any associated files if delete_files is
2342          * true. Even if this part failes, we return succes
2343          * because the driver doesn not exist any more
2344          */
2345         if (delete_files) {
2346                 delete_driver_files(get_session_info_system(), info);
2347         }
2348
2349 done:
2350         talloc_free(tmp_ctx);
2351         return status;
2352 }
2353
2354
2355 /********************************************************************
2356  GetPrinterData on a printer server Handle.
2357 ********************************************************************/
2358
2359 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2360                                             const char *value,
2361                                             enum winreg_Type *type,
2362                                             union spoolss_PrinterData *data)
2363 {
2364         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2365
2366         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2367                 *type = REG_DWORD;
2368                 data->value = 0x00;
2369                 return WERR_OK;
2370         }
2371
2372         if (!strcasecmp_m(value, "BeepEnabled")) {
2373                 *type = REG_DWORD;
2374                 data->value = 0x00;
2375                 return WERR_OK;
2376         }
2377
2378         if (!strcasecmp_m(value, "EventLog")) {
2379                 *type = REG_DWORD;
2380                 /* formally was 0x1b */
2381                 data->value = 0x00;
2382                 return WERR_OK;
2383         }
2384
2385         if (!strcasecmp_m(value, "NetPopup")) {
2386                 *type = REG_DWORD;
2387                 data->value = 0x00;
2388                 return WERR_OK;
2389         }
2390
2391         if (!strcasecmp_m(value, "MajorVersion")) {
2392                 *type = REG_DWORD;
2393
2394                 /* Windows NT 4.0 seems to not allow uploading of drivers
2395                    to a server that reports 0x3 as the MajorVersion.
2396                    need to investigate more how Win2k gets around this .
2397                    -- jerry */
2398
2399                 if (RA_WINNT == get_remote_arch()) {
2400                         data->value = 0x02;
2401                 } else {
2402                         data->value = 0x03;
2403                 }
2404
2405                 return WERR_OK;
2406         }
2407
2408         if (!strcasecmp_m(value, "MinorVersion")) {
2409                 *type = REG_DWORD;
2410                 data->value = 0x00;
2411                 return WERR_OK;
2412         }
2413
2414         /* REG_BINARY
2415          *  uint32_t size        = 0x114
2416          *  uint32_t major       = 5
2417          *  uint32_t minor       = [0|1]
2418          *  uint32_t build       = [2195|2600]
2419          *  extra unicode string = e.g. "Service Pack 3"
2420          */
2421         if (!strcasecmp_m(value, "OSVersion")) {
2422                 DATA_BLOB blob;
2423                 enum ndr_err_code ndr_err;
2424                 struct spoolss_OSVersion os;
2425
2426                 os.major                = 5;    /* Windows 2000 == 5.0 */
2427                 os.minor                = 0;
2428                 os.build                = 2195; /* build */
2429                 os.extra_string         = "";   /* leave extra string empty */
2430
2431                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2432                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2433                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2434                         return WERR_GENERAL_FAILURE;
2435                 }
2436
2437                 *type = REG_BINARY;
2438                 data->binary = blob;
2439
2440                 return WERR_OK;
2441         }
2442
2443
2444         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2445                 *type = REG_SZ;
2446
2447                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2448                 W_ERROR_HAVE_NO_MEMORY(data->string);
2449
2450                 return WERR_OK;
2451         }
2452
2453         if (!strcasecmp_m(value, "Architecture")) {
2454                 *type = REG_SZ;
2455                 data->string = talloc_strdup(mem_ctx,
2456                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2457                 W_ERROR_HAVE_NO_MEMORY(data->string);
2458
2459                 return WERR_OK;
2460         }
2461
2462         if (!strcasecmp_m(value, "DsPresent")) {
2463                 *type = REG_DWORD;
2464
2465                 /* only show the publish check box if we are a
2466                    member of a AD domain */
2467
2468                 if (lp_security() == SEC_ADS) {
2469                         data->value = 0x01;
2470                 } else {
2471                         data->value = 0x00;
2472                 }
2473                 return WERR_OK;
2474         }
2475
2476         if (!strcasecmp_m(value, "DNSMachineName")) {
2477                 const char *hostname = get_mydnsfullname();
2478
2479                 if (!hostname) {
2480                         return WERR_BADFILE;
2481                 }
2482
2483                 *type = REG_SZ;
2484                 data->string = talloc_strdup(mem_ctx, hostname);
2485                 W_ERROR_HAVE_NO_MEMORY(data->string);
2486
2487                 return WERR_OK;
2488         }
2489
2490         *type = REG_NONE;
2491
2492         return WERR_INVALID_PARAM;
2493 }
2494
2495 /****************************************************************
2496  _spoolss_GetPrinterData
2497 ****************************************************************/
2498
2499 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2500                                struct spoolss_GetPrinterData *r)
2501 {
2502         struct spoolss_GetPrinterDataEx r2;
2503
2504         r2.in.handle            = r->in.handle;
2505         r2.in.key_name          = "PrinterDriverData";
2506         r2.in.value_name        = r->in.value_name;
2507         r2.in.offered           = r->in.offered;
2508         r2.out.type             = r->out.type;
2509         r2.out.data             = r->out.data;
2510         r2.out.needed           = r->out.needed;
2511
2512         return _spoolss_GetPrinterDataEx(p, &r2);
2513 }
2514
2515 /*********************************************************
2516  Connect to the client machine.
2517 **********************************************************/
2518
2519 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2520                         struct sockaddr_storage *client_ss, const char *remote_machine)
2521 {
2522         NTSTATUS ret;
2523         struct cli_state *the_cli;
2524         struct sockaddr_storage rm_addr;
2525         char addr[INET6_ADDRSTRLEN];
2526
2527         if ( is_zero_addr(client_ss) ) {
2528                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2529                         remote_machine));
2530                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2531                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2532                         return false;
2533                 }
2534                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2535         } else {
2536                 rm_addr = *client_ss;
2537                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2538                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2539                         addr));
2540         }
2541
2542         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2543                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2544                         addr));
2545                 return false;
2546         }
2547
2548         /* setup the connection */
2549         ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2550                 &rm_addr, 0, "IPC$", "IPC",
2551                 "", /* username */
2552                 "", /* domain */
2553                 "", /* password */
2554                 0, lp_client_signing());
2555
2556         if ( !NT_STATUS_IS_OK( ret ) ) {
2557                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2558                         remote_machine ));
2559                 return false;
2560         }
2561
2562         if ( cli_state_protocol(the_cli) != PROTOCOL_NT1 ) {
2563                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2564                 cli_shutdown(the_cli);
2565                 return false;
2566         }
2567
2568         /*
2569          * Ok - we have an anonymous connection to the IPC$ share.
2570          * Now start the NT Domain stuff :-).
2571          */
2572
2573         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2574         if (!NT_STATUS_IS_OK(ret)) {
2575                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2576                         remote_machine, nt_errstr(ret)));
2577                 cli_shutdown(the_cli);
2578                 return false;
2579         }
2580
2581         return true;
2582 }
2583
2584 /***************************************************************************
2585  Connect to the client.
2586 ****************************************************************************/
2587
2588 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2589                                         uint32_t localprinter,
2590                                         enum winreg_Type type,
2591                                         struct policy_handle *handle,
2592                                         struct notify_back_channel **_chan,
2593                                         struct sockaddr_storage *client_ss,
2594                                         struct messaging_context *msg_ctx)
2595 {
2596         WERROR result;
2597         NTSTATUS status;
2598         struct notify_back_channel *chan;
2599
2600         for (chan = back_channels; chan; chan = chan->next) {
2601                 if (memcmp(&chan->client_address, client_ss,
2602                            sizeof(struct sockaddr_storage)) == 0) {
2603                         break;
2604                 }
2605         }
2606
2607         /*
2608          * If it's the first connection, contact the client
2609          * and connect to the IPC$ share anonymously
2610          */
2611         if (!chan) {
2612                 fstring unix_printer;
2613
2614                 /* the +2 is to strip the leading 2 backslashs */
2615                 fstrcpy(unix_printer, printer + 2);
2616
2617                 chan = talloc_zero(NULL, struct notify_back_channel);
2618                 if (!chan) {
2619                         return false;
2620                 }
2621                 chan->client_address = *client_ss;
2622
2623                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2624                         TALLOC_FREE(chan);
2625                         return false;
2626                 }
2627
2628                 DLIST_ADD(back_channels, chan);
2629
2630                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2631                                    receive_notify2_message_list);
2632         }
2633
2634         if (chan->cli_pipe == NULL ||
2635             chan->cli_pipe->binding_handle == NULL) {
2636                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2637                         "NULL %s for printer %s\n",
2638                         chan->cli_pipe == NULL ?
2639                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2640                         printer));
2641                 return false;
2642         }
2643
2644         /*
2645          * Tell the specific printing tdb we want messages for this printer
2646          * by registering our PID.
2647          */
2648
2649         if (!print_notify_register_pid(snum)) {
2650                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2651                           printer));
2652         }
2653
2654         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2655                                                  talloc_tos(),
2656                                                  printer,
2657                                                  localprinter,
2658                                                  type,
2659                                                  0,
2660                                                  NULL,
2661                                                  handle,
2662                                                  &result);
2663         if (!NT_STATUS_IS_OK(status)) {
2664                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2665                 result = ntstatus_to_werror(status);
2666         } else if (!W_ERROR_IS_OK(result)) {
2667                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2668         }
2669
2670         chan->active_connections++;
2671         *_chan = chan;
2672
2673         return (W_ERROR_IS_OK(result));
2674 }
2675
2676 /****************************************************************
2677  ****************************************************************/
2678
2679 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2680                                                              const struct spoolss_NotifyOption *r)
2681 {
2682         struct spoolss_NotifyOption *option;
2683         uint32_t i,k;
2684
2685         if (!r) {
2686                 return NULL;
2687         }
2688
2689         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2690         if (!option) {
2691                 return NULL;
2692         }
2693
2694         *option = *r;
2695
2696         if (!option->count) {
2697                 return option;
2698         }
2699
2700         option->types = talloc_zero_array(option,
2701                 struct spoolss_NotifyOptionType, option->count);
2702         if (!option->types) {
2703                 talloc_free(option);
2704                 return NULL;
2705         }
2706
2707         for (i=0; i < option->count; i++) {
2708                 option->types[i] = r->types[i];
2709
2710                 if (option->types[i].count) {
2711                         option->types[i].fields = talloc_zero_array(option,
2712                                 union spoolss_Field, option->types[i].count);
2713                         if (!option->types[i].fields) {
2714                                 talloc_free(option);
2715                                 return NULL;
2716                         }
2717                         for (k=0; k<option->types[i].count; k++) {
2718                                 option->types[i].fields[k] =
2719                                         r->types[i].fields[k];
2720                         }
2721                 }
2722         }
2723
2724         return option;
2725 }
2726
2727 /****************************************************************
2728  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2729  *
2730  * before replying OK: status=0 a rpc call is made to the workstation
2731  * asking ReplyOpenPrinter
2732  *
2733  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2734  * called from api_spoolss_rffpcnex
2735 ****************************************************************/
2736
2737 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2738                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2739 {
2740         int snum = -1;
2741         struct spoolss_NotifyOption *option = r->in.notify_options;
2742         struct sockaddr_storage client_ss;
2743         socklen_t client_len;
2744
2745         /* store the notify value in the printer struct */
2746
2747         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2748
2749         if (!Printer) {
2750                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2751                         "Invalid handle (%s:%u:%u).\n",
2752                         OUR_HANDLE(r->in.handle)));
2753                 return WERR_BADFID;
2754         }
2755
2756         Printer->notify.flags           = r->in.flags;
2757         Printer->notify.options         = r->in.options;
2758         Printer->notify.printerlocal    = r->in.printer_local;
2759         Printer->notify.msg_ctx         = p->msg_ctx;
2760
2761         TALLOC_FREE(Printer->notify.option);
2762         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2763
2764         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2765
2766         /* Connect to the client machine and send a ReplyOpenPrinter */
2767
2768         if ( Printer->printer_type == SPLHND_SERVER)
2769                 snum = -1;
2770         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2771                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2772                 return WERR_BADFID;
2773
2774         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2775                   "remote_address is %s\n",
2776                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2777
2778         if (!lp_print_notify_backchannel(snum)) {
2779                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2780                         "backchannel disabled\n"));
2781                 return WERR_SERVER_UNAVAILABLE;
2782         }
2783
2784         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2785                                                   (struct sockaddr *) &client_ss,
2786                                                   sizeof(struct sockaddr_storage));
2787         if (client_len < 0) {
2788                 return WERR_NOMEM;
2789         }
2790
2791         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2792                                         Printer->notify.printerlocal, REG_SZ,
2793                                         &Printer->notify.cli_hnd,
2794                                         &Printer->notify.cli_chan,
2795                                         &client_ss, p->msg_ctx)) {
2796                 return WERR_SERVER_UNAVAILABLE;
2797         }
2798
2799         return WERR_OK;
2800 }
2801
2802 /*******************************************************************
2803  * fill a notify_info_data with the servername
2804  ********************************************************************/
2805
2806 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2807                                        int snum,
2808                                        struct spoolss_Notify *data,
2809                                        print_queue_struct *queue,
2810                                        struct spoolss_PrinterInfo2 *pinfo2,
2811                                        TALLOC_CTX *mem_ctx)
2812 {
2813         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2814 }
2815
2816 /*******************************************************************
2817  * fill a notify_info_data with the printername (not including the servername).
2818  ********************************************************************/
2819
2820 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2821                                         int snum,
2822                                         struct spoolss_Notify *data,
2823                                         print_queue_struct *queue,
2824                                         struct spoolss_PrinterInfo2 *pinfo2,
2825                                         TALLOC_CTX *mem_ctx)
2826 {
2827         /* the notify name should not contain the \\server\ part */
2828         const char *p = strrchr(pinfo2->printername, '\\');
2829
2830         if (!p) {
2831                 p = pinfo2->printername;
2832         } else {
2833                 p++;
2834         }
2835
2836         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2837 }
2838
2839 /*******************************************************************
2840  * fill a notify_info_data with the servicename
2841  ********************************************************************/
2842
2843 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2844                                       int snum,
2845                                       struct spoolss_Notify *data,
2846                                       print_queue_struct *queue,
2847                                       struct spoolss_PrinterInfo2 *pinfo2,
2848                                       TALLOC_CTX *mem_ctx)
2849 {
2850         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2851 }
2852
2853 /*******************************************************************
2854  * fill a notify_info_data with the port name
2855  ********************************************************************/
2856
2857 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2858                                      int snum,
2859                                      struct spoolss_Notify *data,
2860                                      print_queue_struct *queue,
2861                                      struct spoolss_PrinterInfo2 *pinfo2,
2862                                      TALLOC_CTX *mem_ctx)
2863 {
2864         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2865 }
2866
2867 /*******************************************************************
2868  * fill a notify_info_data with the printername
2869  * but it doesn't exist, have to see what to do
2870  ********************************************************************/
2871
2872 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2873                                        int snum,
2874                                        struct spoolss_Notify *data,
2875                                        print_queue_struct *queue,
2876                                        struct spoolss_PrinterInfo2 *pinfo2,
2877                                        TALLOC_CTX *mem_ctx)
2878 {
2879         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2880 }
2881
2882 /*******************************************************************
2883  * fill a notify_info_data with the comment
2884  ********************************************************************/
2885
2886 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2887                                    int snum,
2888                                    struct spoolss_Notify *data,
2889                                    print_queue_struct *queue,
2890                                    struct spoolss_PrinterInfo2 *pinfo2,
2891                                    TALLOC_CTX *mem_ctx)
2892 {
2893         const char *p;
2894
2895         if (*pinfo2->comment == '\0') {
2896                 p = lp_comment(snum);
2897         } else {
2898                 p = pinfo2->comment;
2899         }
2900
2901         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2902 }
2903
2904 /*******************************************************************
2905  * fill a notify_info_data with the comment
2906  * location = "Room 1, floor 2, building 3"
2907  ********************************************************************/
2908
2909 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2910                                     int snum,
2911                                     struct spoolss_Notify *data,
2912                                     print_queue_struct *queue,
2913                                     struct spoolss_PrinterInfo2 *pinfo2,
2914                                     TALLOC_CTX *mem_ctx)
2915 {
2916         const char *loc = pinfo2->location;
2917         NTSTATUS status;
2918
2919         status = printer_list_get_printer(mem_ctx,
2920                                           pinfo2->sharename,
2921                                           NULL,
2922                                           &loc,
2923                                           NULL);
2924         if (NT_STATUS_IS_OK(status)) {
2925                 if (loc == NULL) {
2926                         loc = pinfo2->location;
2927                 }
2928         }
2929
2930         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2931 }
2932
2933 /*******************************************************************
2934  * fill a notify_info_data with the device mode
2935  * jfm:xxxx don't to it for know but that's a real problem !!!
2936  ********************************************************************/
2937
2938 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2939                                    int snum,
2940                                    struct spoolss_Notify *data,
2941                                    print_queue_struct *queue,
2942                                    struct spoolss_PrinterInfo2 *pinfo2,
2943                                    TALLOC_CTX *mem_ctx)
2944 {
2945         /* for a dummy implementation we have to zero the fields */
2946         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2947 }
2948
2949 /*******************************************************************
2950  * fill a notify_info_data with the separator file name
2951  ********************************************************************/
2952
2953 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2954                                    int snum,
2955                                    struct spoolss_Notify *data,
2956                                    print_queue_struct *queue,
2957                                    struct spoolss_PrinterInfo2 *pinfo2,
2958                                    TALLOC_CTX *mem_ctx)
2959 {
2960         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2961 }
2962
2963 /*******************************************************************
2964  * fill a notify_info_data with the print processor
2965  * jfm:xxxx return always winprint to indicate we don't do anything to it
2966  ********************************************************************/
2967
2968 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2969                                            int snum,
2970                                            struct spoolss_Notify *data,
2971                                            print_queue_struct *queue,
2972                                            struct spoolss_PrinterInfo2 *pinfo2,
2973                                            TALLOC_CTX *mem_ctx)
2974 {
2975         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2976 }
2977
2978 /*******************************************************************
2979  * fill a notify_info_data with the print processor options
2980  * jfm:xxxx send an empty string
2981  ********************************************************************/
2982
2983 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2984                                       int snum,
2985                                       struct spoolss_Notify *data,
2986                                       print_queue_struct *queue,
2987                                       struct spoolss_PrinterInfo2 *pinfo2,
2988                                       TALLOC_CTX *mem_ctx)
2989 {
2990         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2991 }
2992
2993 /*******************************************************************
2994  * fill a notify_info_data with the data type
2995  * jfm:xxxx always send RAW as data type
2996  ********************************************************************/
2997
2998 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2999                                     int snum,
3000                                     struct spoolss_Notify *data,
3001                                     print_queue_struct *queue,
3002                                     struct spoolss_PrinterInfo2 *pinfo2,
3003                                     TALLOC_CTX *mem_ctx)
3004 {
3005         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
3006 }
3007
3008 /*******************************************************************
3009  * fill a notify_info_data with the security descriptor
3010  * jfm:xxxx send an null pointer to say no security desc
3011  * have to implement security before !
3012  ********************************************************************/
3013
3014 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
3015                                          int snum,
3016                                          struct spoolss_Notify *data,
3017                                          print_queue_struct *queue,
3018                                          struct spoolss_PrinterInfo2 *pinfo2,
3019                                          TALLOC_CTX *mem_ctx)
3020 {
3021         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
3022 }
3023
3024 /*******************************************************************
3025  * fill a notify_info_data with the attributes
3026  * jfm:xxxx a samba printer is always shared
3027  ********************************************************************/
3028
3029 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
3030                                       int snum,
3031                                       struct spoolss_Notify *data,
3032                                       print_queue_struct *queue,
3033                                       struct spoolss_PrinterInfo2 *pinfo2,
3034                                       TALLOC_CTX *mem_ctx)
3035 {
3036         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3037 }
3038
3039 /*******************************************************************
3040  * fill a notify_info_data with the priority
3041  ********************************************************************/
3042
3043 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3044                                     int snum,
3045                                     struct spoolss_Notify *data,
3046                                     print_queue_struct *queue,
3047                                     struct spoolss_PrinterInfo2 *pinfo2,
3048                                     TALLOC_CTX *mem_ctx)
3049 {
3050         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3051 }
3052
3053 /*******************************************************************
3054  * fill a notify_info_data with the default priority
3055  ********************************************************************/
3056
3057 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3058                                             int snum,
3059                                             struct spoolss_Notify *data,
3060                                             print_queue_struct *queue,
3061                                             struct spoolss_PrinterInfo2 *pinfo2,
3062                                             TALLOC_CTX *mem_ctx)
3063 {
3064         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3065 }
3066
3067 /*******************************************************************
3068  * fill a notify_info_data with the start time
3069  ********************************************************************/
3070
3071 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3072                                       int snum,
3073                                       struct spoolss_Notify *data,
3074                                       print_queue_struct *queue,
3075                                       struct spoolss_PrinterInfo2 *pinfo2,
3076                                       TALLOC_CTX *mem_ctx)
3077 {
3078         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3079 }
3080
3081 /*******************************************************************
3082  * fill a notify_info_data with the until time
3083  ********************************************************************/
3084
3085 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3086                                       int snum,
3087                                       struct spoolss_Notify *data,
3088                                       print_queue_struct *queue,
3089                                       struct spoolss_PrinterInfo2 *pinfo2,
3090                                       TALLOC_CTX *mem_ctx)
3091 {
3092         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3093 }
3094
3095 /*******************************************************************
3096  * fill a notify_info_data with the status
3097  ********************************************************************/
3098
3099 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3100                                   int snum,
3101                                   struct spoolss_Notify *data,
3102                                   print_queue_struct *queue,
3103                                   struct spoolss_PrinterInfo2 *pinfo2,
3104                                   TALLOC_CTX *mem_ctx)
3105 {
3106         print_status_struct status;
3107
3108         print_queue_length(msg_ctx, snum, &status);
3109         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3110 }
3111
3112 /*******************************************************************
3113  * fill a notify_info_data with the number of jobs queued
3114  ********************************************************************/
3115
3116 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3117                                  int snum,
3118                                  struct spoolss_Notify *data,
3119                                  print_queue_struct *queue,
3120                                  struct spoolss_PrinterInfo2 *pinfo2,
3121                                  TALLOC_CTX *mem_ctx)
3122 {
3123         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3124                 data, print_queue_length(msg_ctx, snum, NULL));
3125 }
3126
3127 /*******************************************************************
3128  * fill a notify_info_data with the average ppm
3129  ********************************************************************/
3130
3131 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3132                                        int snum,
3133                                        struct spoolss_Notify *data,
3134                                        print_queue_struct *queue,
3135                                        struct spoolss_PrinterInfo2 *pinfo2,
3136                                        TALLOC_CTX *mem_ctx)
3137 {
3138         /* always respond 8 pages per minutes */
3139         /* a little hard ! */
3140         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3141 }
3142
3143 /*******************************************************************
3144  * fill a notify_info_data with username
3145  ********************************************************************/
3146
3147 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3148                                     int snum,
3149                                     struct spoolss_Notify *data,
3150                                     print_queue_struct *queue,
3151                                     struct spoolss_PrinterInfo2 *pinfo2,
3152                                     TALLOC_CTX *mem_ctx)
3153 {
3154         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3155 }
3156
3157 /*******************************************************************
3158  * fill a notify_info_data with job status
3159  ********************************************************************/
3160
3161 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3162                                       int snum,
3163                                       struct spoolss_Notify *data,
3164                                       print_queue_struct *queue,
3165                                       struct spoolss_PrinterInfo2 *pinfo2,
3166                                       TALLOC_CTX *mem_ctx)
3167 {
3168         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3169 }
3170
3171 /*******************************************************************
3172  * fill a notify_info_data with job name
3173  ********************************************************************/
3174
3175 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3176                                     int snum,
3177                                     struct spoolss_Notify *data,
3178                                     print_queue_struct *queue,
3179                                     struct spoolss_PrinterInfo2 *pinfo2,
3180                                     TALLOC_CTX *mem_ctx)
3181 {
3182         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3183 }
3184
3185 /*******************************************************************
3186  * fill a notify_info_data with job status
3187  ********************************************************************/
3188
3189 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3190                                              int snum,
3191                                              struct spoolss_Notify *data,
3192                                              print_queue_struct *queue,
3193                                              struct spoolss_PrinterInfo2 *pinfo2,
3194                                              TALLOC_CTX *mem_ctx)
3195 {
3196         /*
3197          * Now we're returning job status codes we just return a "" here. JRA.
3198          */
3199
3200         const char *p = "";
3201
3202 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3203         p = "unknown";
3204
3205         switch (queue->status) {
3206         case LPQ_QUEUED:
3207                 p = "Queued";
3208                 break;
3209         case LPQ_PAUSED:
3210                 p = "";    /* NT provides the paused string */
3211                 break;
3212         case LPQ_SPOOLING:
3213                 p = "Spooling";
3214                 break;
3215         case LPQ_PRINTING:
3216                 p = "Printing";
3217                 break;
3218         }
3219 #endif /* NO LONGER NEEDED. */
3220
3221         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3222 }
3223
3224 /*******************************************************************
3225  * fill a notify_info_data with job time
3226  ********************************************************************/
3227
3228 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3229                                     int snum,
3230                                     struct spoolss_Notify *data,
3231                                     print_queue_struct *queue,
3232                                     struct spoolss_PrinterInfo2 *pinfo2,
3233                                     TALLOC_CTX *mem_ctx)
3234 {
3235         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3236 }
3237
3238 /*******************************************************************
3239  * fill a notify_info_data with job size
3240  ********************************************************************/
3241
3242 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3243                                     int snum,
3244                                     struct spoolss_Notify *data,
3245                                     print_queue_struct *queue,
3246                                     struct spoolss_PrinterInfo2 *pinfo2,
3247                                     TALLOC_CTX *mem_ctx)
3248 {
3249         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3250 }
3251
3252 /*******************************************************************
3253  * fill a notify_info_data with page info
3254  ********************************************************************/
3255 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3256                                        int snum,
3257                                 struct spoolss_Notify *data,
3258                                 print_queue_struct *queue,
3259                                 struct spoolss_PrinterInfo2 *pinfo2,
3260                                 TALLOC_CTX *mem_ctx)
3261 {
3262         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3263 }
3264
3265 /*******************************************************************
3266  * fill a notify_info_data with pages printed info.
3267  ********************************************************************/
3268 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3269                                          int snum,
3270                                 struct spoolss_Notify *data,
3271                                 print_queue_struct *queue,
3272                                 struct spoolss_PrinterInfo2 *pinfo2,
3273                                 TALLOC_CTX *mem_ctx)
3274 {
3275         /* Add code when back-end tracks this */
3276         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3277 }
3278
3279 /*******************************************************************
3280  Fill a notify_info_data with job position.
3281  ********************************************************************/
3282
3283 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3284                                         int snum,
3285                                         struct spoolss_Notify *data,
3286                                         print_queue_struct *queue,
3287                                         struct spoolss_PrinterInfo2 *pinfo2,
3288                                         TALLOC_CTX *mem_ctx)
3289 {
3290         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3291 }
3292
3293 /*******************************************************************
3294  Fill a notify_info_data with submitted time.
3295  ********************************************************************/
3296
3297 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3298                                           int snum,
3299                                           struct spoolss_Notify *data,
3300                                           print_queue_struct *queue,
3301                                           struct spoolss_PrinterInfo2 *pinfo2,
3302                                           TALLOC_CTX *mem_ctx)
3303 {
3304         data->data.string.string = NULL;
3305         data->data.string.size = 0;
3306
3307         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3308                                &data->data.string.string,
3309                                &data->data.string.size);
3310
3311 }
3312
3313 struct s_notify_info_data_table
3314 {
3315         enum spoolss_NotifyType type;
3316         uint16_t field;
3317         const char *name;
3318         enum spoolss_NotifyTable variable_type;
3319         void (*fn) (struct messaging_context *msg_ctx,
3320                     int snum, struct spoolss_Notify *data,
3321                     print_queue_struct *queue,
3322                     struct spoolss_PrinterInfo2 *pinfo2,
3323                     TALLOC_CTX *mem_ctx);
3324 };
3325
3326 /* A table describing the various print notification constants and
3327    whether the notification data is a pointer to a variable sized
3328    buffer, a one value uint32_t or a two value uint32_t. */
3329
3330 static const struct s_notify_info_data_table notify_info_data_table[] =
3331 {
3332 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3333 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3334 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3335 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3336 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3337 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3338 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3339 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3340 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3341 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3342 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3343 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3344 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3345 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3346 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3347 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3348 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3349 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3350 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3351 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3352 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3353 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3354 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3355 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3356 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3357 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3358 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3359 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3360 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3361 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3362 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3363 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3364 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3365 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3366 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3367 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3368 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3369 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3370 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3371 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3372 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3373 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3374 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3375 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3376 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3377 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3378 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3379 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3380 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3381 };
3382
3383 /*******************************************************************
3384  Return the variable_type of info_data structure.
3385 ********************************************************************/
3386
3387 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3388                                                                   uint16_t field)
3389 {
3390         int i=0;
3391
3392         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3393                 if ( (notify_info_data_table[i].type == type) &&
3394                      (notify_info_data_table[i].field == field) ) {
3395                         return notify_info_data_table[i].variable_type;
3396                 }
3397         }
3398
3399         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3400
3401         return (enum spoolss_NotifyTable) 0;
3402 }
3403
3404 /****************************************************************************
3405 ****************************************************************************/
3406
3407 static bool search_notify(enum spoolss_NotifyType type,
3408                           uint16_t field,
3409                           int *value)
3410 {
3411         int i;
3412
3413         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3414                 if (notify_info_data_table[i].type == type &&
3415                     notify_info_data_table[i].field == field &&
3416                     notify_info_data_table[i].fn != NULL) {
3417                         *value = i;
3418                         return true;
3419                 }
3420         }
3421
3422         return false;
3423 }
3424
3425 /****************************************************************************
3426 ****************************************************************************/
3427
3428 static void construct_info_data(struct spoolss_Notify *info_data,
3429                                 enum spoolss_NotifyType type,
3430                                 uint16_t field, int id)
3431 {
3432         info_data->type                 = type;
3433         info_data->field.field          = field;
3434         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3435         info_data->job_id               = id;
3436 }
3437
3438 /*******************************************************************
3439  *
3440  * fill a notify_info struct with info asked
3441  *
3442  ********************************************************************/
3443
3444 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3445                                           struct printer_handle *print_hnd,
3446                                           struct spoolss_NotifyInfo *info,
3447                                           struct spoolss_PrinterInfo2 *pinfo2,
3448                                           int snum,
3449                                           const struct spoolss_NotifyOptionType *option_type,
3450                                           uint32_t id,
3451                                           TALLOC_CTX *mem_ctx)
3452 {
3453         int field_num,j;
3454         enum spoolss_NotifyType type;
3455         uint16_t field;
3456
3457         struct spoolss_Notify *current_data;
3458
3459         type = option_type->type;
3460
3461         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3462                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3463                 option_type->count, lp_servicename(snum)));
3464
3465         for(field_num=0; field_num < option_type->count; field_num++) {
3466                 field = option_type->fields[field_num].field;
3467
3468                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3469
3470                 if (!search_notify(type, field, &j) )
3471                         continue;
3472
3473                 info->notifies = talloc_realloc(info, info->notifies,
3474                                                       struct spoolss_Notify,
3475                                                       info->count + 1);
3476                 if (info->notifies == NULL) {
3477                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3478                         return false;
3479                 }
3480
3481                 current_data = &info->notifies[info->count];
3482
3483                 construct_info_data(current_data, type, field, id);
3484
3485                 DEBUG(10, ("construct_notify_printer_info: "
3486                            "calling [%s]  snum=%d  printername=[%s])\n",
3487                            notify_info_data_table[j].name, snum,
3488                            pinfo2->printername));
3489
3490                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3491                                              NULL, pinfo2, mem_ctx);
3492
3493                 info->count++;
3494         }
3495
3496         return true;
3497 }
3498
3499 /*******************************************************************
3500  *
3501  * fill a notify_info struct with info asked
3502  *
3503  ********************************************************************/
3504
3505 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3506                                        print_queue_struct *queue,
3507                                        struct spoolss_NotifyInfo *info,
3508                                        struct spoolss_PrinterInfo2 *pinfo2,
3509                                        int snum,
3510                                        const struct spoolss_NotifyOptionType *option_type,
3511                                        uint32_t id,
3512                                        TALLOC_CTX *mem_ctx)
3513 {
3514         int field_num,j;
3515         enum spoolss_NotifyType type;
3516         uint16_t field;
3517         struct spoolss_Notify *current_data;
3518
3519         DEBUG(4,("construct_notify_jobs_info\n"));
3520
3521         type = option_type->type;
3522
3523         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3524                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3525                 option_type->count));
3526
3527         for(field_num=0; field_num<option_type->count; field_num++) {
3528                 field = option_type->fields[field_num].field;
3529
3530                 if (!search_notify(type, field, &j) )
3531                         continue;
3532
3533                 info->notifies = talloc_realloc(info, info->notifies,
3534                                                       struct spoolss_Notify,
3535                                                       info->count + 1);
3536                 if (info->notifies == NULL) {
3537                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3538                         return false;
3539                 }
3540
3541                 current_data=&(info->notifies[info->count]);
3542
3543                 construct_info_data(current_data, type, field, id);
3544                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3545                                              queue, pinfo2, mem_ctx);
3546                 info->count++;
3547         }
3548
3549         return true;
3550 }
3551
3552 /*
3553  * JFM: The enumeration is not that simple, it's even non obvious.
3554  *
3555  * let's take an example: I want to monitor the PRINTER SERVER for
3556  * the printer's name and the number of jobs currently queued.
3557  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3558  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3559  *
3560  * I have 3 printers on the back of my server.
3561  *
3562  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3563  * structures.
3564  *   Number     Data                    Id
3565  *      1       printer 1 name          1
3566  *      2       printer 1 cjob          1
3567  *      3       printer 2 name          2
3568  *      4       printer 2 cjob          2
3569  *      5       printer 3 name          3
3570  *      6       printer 3 name          3
3571  *
3572  * that's the print server case, the printer case is even worse.
3573  */
3574
3575 /*******************************************************************
3576  *
3577  * enumerate all printers on the printserver
3578  * fill a notify_info struct with info asked
3579  *
3580  ********************************************************************/
3581
3582 static WERROR printserver_notify_info(struct pipes_struct *p,
3583                                       struct policy_handle *hnd,
3584                                       struct spoolss_NotifyInfo *info,
3585                                       TALLOC_CTX *mem_ctx)
3586 {
3587         int snum;
3588         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3589         int n_services=lp_numservices();
3590         int i;
3591         struct spoolss_NotifyOption *option;
3592         struct spoolss_NotifyOptionType option_type;
3593         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3594         WERROR result;
3595
3596         DEBUG(4,("printserver_notify_info\n"));
3597
3598         if (!Printer)
3599                 return WERR_BADFID;
3600
3601         option = Printer->notify.option;
3602
3603         info->version   = 2;
3604         info->notifies  = NULL;
3605         info->count     = 0;
3606
3607         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3608            sending a ffpcn() request first */
3609
3610         if ( !option )
3611                 return WERR_BADFID;
3612
3613         for (i=0; i<option->count; i++) {
3614                 option_type = option->types[i];
3615
3616                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3617                         continue;
3618
3619                 for (snum = 0; snum < n_services; snum++) {
3620                         if (!lp_browseable(snum) ||
3621                             !lp_snum_ok(snum) ||
3622                             !lp_print_ok(snum)) {
3623                                 continue; /* skip */
3624                         }
3625
3626                         /* Maybe we should use the SYSTEM session_info here... */
3627                         result = winreg_get_printer_internal(mem_ctx,
3628                                                     get_session_info_system(),
3629                                                     p->msg_ctx,
3630                                                     lp_servicename(snum),
3631                                                     &pinfo2);
3632                         if (!W_ERROR_IS_OK(result)) {
3633                                 DEBUG(4, ("printserver_notify_info: "
3634                                           "Failed to get printer [%s]\n",
3635                                           lp_servicename(snum)));
3636                                 continue;
3637                         }
3638
3639
3640                         construct_notify_printer_info(p->msg_ctx,
3641                                                       Printer, info,
3642                                                       pinfo2, snum,
3643                                                       &option_type, snum,
3644                                                       mem_ctx);
3645
3646                         TALLOC_FREE(pinfo2);
3647                 }
3648         }
3649
3650 #if 0
3651         /*
3652          * Debugging information, don't delete.
3653          */
3654
3655         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3656         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3657         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3658
3659         for (i=0; i<info->count; i++) {
3660                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3661                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3662                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3663         }
3664 #endif
3665
3666         return WERR_OK;
3667 }
3668
3669 /*******************************************************************
3670  *
3671  * fill a notify_info struct with info asked
3672  *
3673  ********************************************************************/
3674
3675 static WERROR printer_notify_info(struct pipes_struct *p,
3676                                   struct policy_handle *hnd,
3677                                   struct spoolss_NotifyInfo *info,
3678                                   TALLOC_CTX *mem_ctx)
3679 {
3680         int snum;
3681         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3682         int i;
3683         uint32_t id;
3684         struct spoolss_NotifyOption *option;
3685         struct spoolss_NotifyOptionType option_type;
3686         int count,j;
3687         print_queue_struct *queue=NULL;
3688         print_status_struct status;
3689         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3690         WERROR result;
3691
3692         DEBUG(4,("printer_notify_info\n"));
3693
3694         if (!Printer)
3695                 return WERR_BADFID;
3696
3697         option = Printer->notify.option;
3698         id = 0x0;
3699
3700         info->version   = 2;
3701         info->notifies  = NULL;
3702         info->count     = 0;
3703
3704         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3705            sending a ffpcn() request first */
3706
3707         if ( !option )
3708                 return WERR_BADFID;
3709
3710         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3711                 return WERR_BADFID;
3712         }
3713
3714         /* Maybe we should use the SYSTEM session_info here... */
3715         result = winreg_get_printer_internal(mem_ctx,
3716                                     get_session_info_system(),
3717                                     p->msg_ctx,
3718                                     lp_servicename(snum), &pinfo2);
3719         if (!W_ERROR_IS_OK(result)) {
3720                 return WERR_BADFID;
3721         }
3722
3723         /*
3724          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3725          * correct servername.
3726          */
3727         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3728         if (pinfo2->servername == NULL) {
3729                 return WERR_NOMEM;
3730         }
3731
3732         for (i=0; i<option->count; i++) {
3733                 option_type = option->types[i];
3734
3735                 switch (option_type.type) {
3736                 case PRINTER_NOTIFY_TYPE:
3737                         if (construct_notify_printer_info(p->msg_ctx,
3738                                                           Printer, info,
3739                                                           pinfo2, snum,
3740                                                           &option_type, id,
3741                                                           mem_ctx)) {
3742                                 id--;
3743                         }
3744                         break;
3745
3746                 case JOB_NOTIFY_TYPE:
3747
3748                         count = print_queue_status(p->msg_ctx, snum, &queue,
3749                                                    &status);
3750
3751                         for (j=0; j<count; j++) {
3752                                 construct_notify_jobs_info(p->msg_ctx,
3753                                                            &queue[j], info,
3754                                                            pinfo2, snum,
3755                                                            &option_type,
3756                                                            queue[j].job,
3757                                                            mem_ctx);
3758                         }
3759
3760                         SAFE_FREE(queue);
3761                         break;
3762                 }
3763         }
3764
3765         /*
3766          * Debugging information, don't delete.
3767          */
3768         /*
3769         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3770         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3771         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3772
3773         for (i=0; i<info->count; i++) {
3774                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3775                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3776                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3777         }
3778         */
3779
3780         talloc_free(pinfo2);
3781         return WERR_OK;
3782 }
3783
3784 /****************************************************************
3785  _spoolss_RouterRefreshPrinterChangeNotify
3786 ****************************************************************/
3787
3788 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3789                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3790 {
3791         struct spoolss_NotifyInfo *info;
3792
3793         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3794         WERROR result = WERR_BADFID;
3795
3796         /* we always have a spoolss_NotifyInfo struct */
3797         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3798         if (!info) {
3799                 result = WERR_NOMEM;
3800                 goto done;
3801         }
3802
3803         *r->out.info = info;
3804
3805         if (!Printer) {
3806                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3807                         "Invalid handle (%s:%u:%u).\n",
3808                         OUR_HANDLE(r->in.handle)));
3809                 goto done;
3810         }
3811
3812         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3813
3814         /*
3815          *      We are now using the change value, and
3816          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3817          *      I don't have a global notification system, I'm sending back all the
3818          *      information even when _NOTHING_ has changed.
3819          */
3820
3821         /* We need to keep track of the change value to send back in
3822            RRPCN replies otherwise our updates are ignored. */
3823
3824         Printer->notify.fnpcn = true;
3825
3826         if (Printer->notify.cli_chan != NULL &&
3827             Printer->notify.cli_chan->active_connections > 0) {
3828                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3829                         "Saving change value in request [%x]\n",
3830                         r->in.change_low));
3831                 Printer->notify.change = r->in.change_low;
3832         }
3833
3834         /* just ignore the spoolss_NotifyOption */
3835
3836         switch (Printer->printer_type) {
3837                 case SPLHND_SERVER:
3838                         result = printserver_notify_info(p, r->in.handle,
3839                                                          info, p->mem_ctx);
3840                         break;
3841
3842                 case SPLHND_PRINTER:
3843                         result = printer_notify_info(p, r->in.handle,
3844                                                      info, p->mem_ctx);
3845                         break;
3846         }
3847
3848         Printer->notify.fnpcn = false;
3849
3850 done:
3851         return result;
3852 }
3853
3854 /********************************************************************
3855  ********************************************************************/
3856
3857 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3858                                  const char *servername,
3859                                  const char *printername,
3860                                  const char **printername_p)
3861 {
3862         /* FIXME: add lp_force_printername() */
3863
3864         if (servername == NULL) {
3865                 *printername_p = talloc_strdup(mem_ctx, printername);
3866                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3867                 return WERR_OK;
3868         }
3869
3870         if (servername[0] == '\\' && servername[1] == '\\') {
3871                 servername += 2;
3872         }
3873
3874         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3875         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3876
3877         return WERR_OK;
3878 }
3879
3880 /********************************************************************
3881  ********************************************************************/
3882
3883 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3884                                           const char *printername)
3885 {
3886         if (dm == NULL) {
3887                 return;
3888         }
3889
3890         dm->devicename = talloc_strndup(dm, printername,
3891                                         MIN(strlen(printername), 31));
3892 }
3893
3894 /********************************************************************
3895  * construct_printer_info_0
3896  * fill a printer_info_0 struct
3897  ********************************************************************/
3898
3899 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3900                                       const struct auth_session_info *session_info,
3901                                       struct messaging_context *msg_ctx,
3902                                       struct spoolss_PrinterInfo2 *info2,
3903                                       const char *servername,
3904                                       struct spoolss_PrinterInfo0 *r,
3905                                       int snum)
3906 {
3907         int count;
3908         struct printer_session_counter *session_counter;
3909         struct timeval setuptime;
3910         print_status_struct status;
3911         WERROR result;
3912
3913         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3914         if (!W_ERROR_IS_OK(result)) {
3915                 return result;
3916         }
3917
3918         if (servername) {
3919                 r->servername = talloc_strdup(mem_ctx, servername);
3920                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3921         } else {
3922                 r->servername = NULL;
3923         }
3924
3925         count = print_queue_length(msg_ctx, snum, &status);
3926
3927         /* check if we already have a counter for this printer */
3928         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3929                 if (session_counter->snum == snum)
3930                         break;
3931         }
3932
3933         /* it's the first time, add it to the list */
3934         if (session_counter == NULL) {
3935                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3936                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3937                 session_counter->snum           = snum;
3938                 session_counter->counter        = 0;
3939                 DLIST_ADD(counter_list, session_counter);
3940         }
3941
3942         /* increment it */
3943         session_counter->counter++;
3944
3945         r->cjobs                        = count;
3946         r->total_jobs                   = 0;
3947         r->total_bytes                  = 0;
3948
3949         get_startup_time(&setuptime);
3950         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3951
3952         /* JFM:
3953          * the global_counter should be stored in a TDB as it's common to all the clients
3954          * and should be zeroed on samba startup
3955          */
3956         r->global_counter               = session_counter->counter;
3957         r->total_pages                  = 0;
3958         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3959         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3960         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3961         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3962         r->spooling                     = 0;
3963         r->max_spooling                 = 0;
3964         r->session_counter              = session_counter->counter;
3965         r->num_error_out_of_paper       = 0x0;
3966         r->num_error_not_ready          = 0x0;          /* number of print failure */
3967         r->job_error                    = 0x0;
3968         r->number_of_processors         = 0x1;
3969         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3970         r->high_part_total_bytes        = 0x0;
3971
3972         /* ChangeID in milliseconds*/
3973         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3974                                     info2->sharename, &r->change_id);
3975
3976         r->last_error                   = WERR_OK;
3977         r->status                       = nt_printq_status(status.status);
3978         r->enumerate_network_printers   = 0x0;
3979         r->c_setprinter                 = 0x0;
3980         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3981         r->processor_level              = 0x6;          /* 6  ???*/
3982         r->ref_ic                       = 0;
3983         r->reserved2                    = 0;
3984         r->reserved3                    = 0;
3985
3986         return WERR_OK;
3987 }
3988
3989
3990 /********************************************************************
3991  * construct_printer_info1
3992  * fill a spoolss_PrinterInfo1 struct
3993 ********************************************************************/
3994
3995 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3996                                       const struct spoolss_PrinterInfo2 *info2,
3997                                       uint32_t flags,
3998                                       const char *servername,
3999                                       struct spoolss_PrinterInfo1 *r,
4000                                       int snum)
4001 {
4002         WERROR result;
4003
4004         r->flags                = flags;
4005
4006         if (info2->comment == NULL || info2->comment[0] == '\0') {
4007                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4008         } else {
4009                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4010         }
4011         W_ERROR_HAVE_NO_MEMORY(r->comment);
4012
4013         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4014         if (!W_ERROR_IS_OK(result)) {
4015                 return result;
4016         }
4017
4018         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
4019                                                   r->name,
4020                                                   info2->drivername,
4021                                                   r->comment);
4022         W_ERROR_HAVE_NO_MEMORY(r->description);
4023
4024         return WERR_OK;
4025 }
4026
4027 /********************************************************************
4028  * construct_printer_info2
4029  * fill a spoolss_PrinterInfo2 struct
4030 ********************************************************************/
4031
4032 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4033                                       struct messaging_context *msg_ctx,
4034                                       const struct spoolss_PrinterInfo2 *info2,
4035                                       const char *servername,
4036                                       struct spoolss_PrinterInfo2 *r,
4037                                       int snum)
4038 {
4039         int count;
4040         print_status_struct status;
4041         WERROR result;
4042
4043         count = print_queue_length(msg_ctx, snum, &status);
4044
4045         if (servername) {
4046                 r->servername           = talloc_strdup(mem_ctx, servername);
4047                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4048         } else {
4049                 r->servername           = NULL;
4050         }
4051
4052         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4053         if (!W_ERROR_IS_OK(result)) {
4054                 return result;
4055         }
4056
4057         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4058         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4059         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4060         W_ERROR_HAVE_NO_MEMORY(r->portname);
4061         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4062         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4063
4064         if (info2->comment[0] == '\0') {
4065                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4066         } else {
4067                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4068         }
4069         W_ERROR_HAVE_NO_MEMORY(r->comment);
4070
4071         r->location     = talloc_strdup(mem_ctx, info2->location);
4072         if (info2->location[0] == '\0') {
4073                 const char *loc = NULL;
4074                 NTSTATUS nt_status;
4075
4076                 nt_status = printer_list_get_printer(mem_ctx,
4077                                                      info2->sharename,
4078                                                      NULL,
4079                                                      &loc,
4080                                                      NULL);
4081                 if (NT_STATUS_IS_OK(nt_status)) {
4082                         if (loc != NULL) {
4083                                 r->location = talloc_strdup(mem_ctx, loc);
4084                         }
4085                 }
4086         }
4087         W_ERROR_HAVE_NO_MEMORY(r->location);
4088
4089         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4090         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4091         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4092         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4093         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4094         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4095         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4096         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4097
4098         r->attributes           = info2->attributes;
4099
4100         r->priority             = info2->priority;
4101         r->defaultpriority      = info2->defaultpriority;
4102         r->starttime            = info2->starttime;
4103         r->untiltime            = info2->untiltime;
4104         r->status               = nt_printq_status(status.status);
4105         r->cjobs                = count;
4106         r->averageppm           = info2->averageppm;
4107
4108         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4109         if (!r->devmode) {
4110                 DEBUG(8,("Returning NULL Devicemode!\n"));
4111         }
4112
4113         compose_devicemode_devicename(r->devmode, r->printername);
4114
4115         r->secdesc = NULL;
4116
4117         if (info2->secdesc != NULL) {
4118                 /* don't use talloc_steal() here unless you do a deep steal of all
4119                    the SEC_DESC members */
4120
4121                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4122         }
4123
4124         return WERR_OK;
4125 }
4126
4127 /********************************************************************
4128  * construct_printer_info3
4129  * fill a spoolss_PrinterInfo3 struct
4130  ********************************************************************/
4131
4132 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4133                                       const struct spoolss_PrinterInfo2 *info2,
4134                                       const char *servername,
4135                                       struct spoolss_PrinterInfo3 *r,
4136                                       int snum)
4137 {
4138         /* These are the components of the SD we are returning. */
4139
4140         if (info2->secdesc != NULL) {
4141                 /* don't use talloc_steal() here unless you do a deep steal of all
4142                    the SEC_DESC members */
4143
4144                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4145                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4146         }
4147
4148         return WERR_OK;
4149 }
4150
4151 /********************************************************************
4152  * construct_printer_info4
4153  * fill a spoolss_PrinterInfo4 struct
4154  ********************************************************************/
4155
4156 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4157                                       const struct spoolss_PrinterInfo2 *info2,
4158                                       const char *servername,
4159                                       struct spoolss_PrinterInfo4 *r,
4160                                       int snum)
4161 {
4162         WERROR result;
4163
4164         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4165         if (!W_ERROR_IS_OK(result)) {
4166                 return result;
4167         }
4168
4169         if (servername) {
4170                 r->servername   = talloc_strdup(mem_ctx, servername);
4171                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4172         } else {
4173                 r->servername = NULL;
4174         }
4175
4176         r->attributes   = info2->attributes;
4177
4178         return WERR_OK;
4179 }
4180
4181 /********************************************************************
4182  * construct_printer_info5
4183  * fill a spoolss_PrinterInfo5 struct
4184  ********************************************************************/
4185
4186 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4187                                       const struct spoolss_PrinterInfo2 *info2,
4188                                       const char *servername,
4189                                       struct spoolss_PrinterInfo5 *r,
4190                                       int snum)
4191 {
4192         WERROR result;
4193
4194         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4195         if (!W_ERROR_IS_OK(result)) {
4196                 return result;
4197         }
4198
4199         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4200         W_ERROR_HAVE_NO_MEMORY(r->portname);
4201
4202         r->attributes   = info2->attributes;
4203
4204         /* these two are not used by NT+ according to MSDN */
4205         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4206         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4207
4208         return WERR_OK;
4209 }
4210
4211 /********************************************************************
4212  * construct_printer_info_6
4213  * fill a spoolss_PrinterInfo6 struct
4214  ********************************************************************/
4215
4216 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4217                                       struct messaging_context *msg_ctx,
4218                                       const struct spoolss_PrinterInfo2 *info2,
4219                                       const char *servername,
4220                                       struct spoolss_PrinterInfo6 *r,
4221                                       int snum)
4222 {
4223         print_status_struct status;
4224
4225         print_queue_length(msg_ctx, snum, &status);
4226
4227         r->status = nt_printq_status(status.status);
4228
4229         return WERR_OK;
4230 }
4231
4232 /********************************************************************
4233  * construct_printer_info7
4234  * fill a spoolss_PrinterInfo7 struct
4235  ********************************************************************/
4236
4237 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4238                                       struct messaging_context *msg_ctx,
4239                                       const char *servername,
4240                                       struct spoolss_PrinterInfo7 *r,
4241                                       int snum)
4242 {
4243         const struct auth_session_info *session_info = get_session_info_system();
4244         struct GUID guid;
4245
4246         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4247                                  servername,
4248                                  lp_servicename(snum), &guid, NULL)) {
4249                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4250                 r->action = DSPRINT_PUBLISH;
4251         } else {
4252                 r->guid = talloc_strdup(mem_ctx, "");
4253                 r->action = DSPRINT_UNPUBLISH;
4254         }
4255         W_ERROR_HAVE_NO_MEMORY(r->guid);
4256
4257         return WERR_OK;
4258 }
4259
4260 /********************************************************************
4261  * construct_printer_info8
4262  * fill a spoolss_PrinterInfo8 struct
4263  ********************************************************************/
4264
4265 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4266                                       const struct spoolss_PrinterInfo2 *info2,
4267                                       const char *servername,
4268                                       struct spoolss_DeviceModeInfo *r,
4269                                       int snum)
4270 {
4271         WERROR result;
4272         const char *printername;
4273
4274         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4275         if (!W_ERROR_IS_OK(result)) {
4276                 return result;
4277         }
4278
4279         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4280         if (!r->devmode) {
4281                 DEBUG(8,("Returning NULL Devicemode!\n"));
4282         }
4283
4284         compose_devicemode_devicename(r->devmode, printername);
4285
4286         return WERR_OK;
4287 }
4288
4289
4290 /********************************************************************
4291 ********************************************************************/
4292
4293 static bool snum_is_shared_printer(int snum)
4294 {
4295         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4296 }
4297
4298 /********************************************************************
4299  Spoolss_enumprinters.
4300 ********************************************************************/
4301
4302 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4303                                            const struct auth_session_info *session_info,
4304                                            struct messaging_context *msg_ctx,
4305                                            const char *servername,
4306                                            uint32_t level,
4307                                            uint32_t flags,
4308                                            union spoolss_PrinterInfo **info_p,
4309                                            uint32_t *count_p)
4310 {
4311         int snum;
4312         int n_services = lp_numservices();
4313         union spoolss_PrinterInfo *info = NULL;
4314         uint32_t count = 0;
4315         WERROR result = WERR_OK;
4316         struct dcerpc_binding_handle *b = NULL;
4317         TALLOC_CTX *tmp_ctx = NULL;
4318
4319         tmp_ctx = talloc_new(mem_ctx);
4320         if (!tmp_ctx) {
4321                 return WERR_NOMEM;
4322         }
4323
4324         *count_p = 0;
4325         *info_p = NULL;
4326
4327         for (snum = 0; snum < n_services; snum++) {
4328
4329                 const char *printer;
4330                 struct spoolss_PrinterInfo2 *info2;
4331
4332                 if (!snum_is_shared_printer(snum)) {
4333                         continue;
4334                 }
4335
4336                 printer = lp_const_servicename(snum);
4337
4338                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4339                         printer, snum));
4340
4341                 if (b == NULL) {
4342                         result = winreg_printer_binding_handle(tmp_ctx,
4343                                                                session_info,
4344                                                                msg_ctx,
4345                                                                &b);
4346                         if (!W_ERROR_IS_OK(result)) {
4347                                 goto out;
4348                         }
4349                 }
4350
4351                 result = winreg_create_printer(tmp_ctx, b,
4352                                                printer);
4353                 if (!W_ERROR_IS_OK(result)) {
4354                         goto out;
4355                 }
4356
4357                 info = talloc_realloc(tmp_ctx, info,
4358                                             union spoolss_PrinterInfo,
4359                                             count + 1);
4360                 if (!info) {
4361                         result = WERR_NOMEM;
4362                         goto out;
4363                 }
4364
4365                 result = winreg_get_printer(tmp_ctx, b,
4366                                             printer, &info2);
4367                 if (!W_ERROR_IS_OK(result)) {
4368                         goto out;
4369                 }
4370
4371                 switch (level) {
4372                 case 0:
4373                         result = construct_printer_info0(info, session_info,
4374                                                          msg_ctx, info2,
4375                                                          servername,
4376                                                          &info[count].info0, snum);
4377                         break;
4378                 case 1:
4379                         result = construct_printer_info1(info, info2, flags,
4380                                                          servername,
4381                                                          &info[count].info1, snum);
4382                         break;
4383                 case 2:
4384                         result = construct_printer_info2(info, msg_ctx, info2,
4385                                                          servername,
4386                                                          &info[count].info2, snum);
4387                         break;
4388                 case 4:
4389                         result = construct_printer_info4(info, info2,
4390                                                          servername,
4391                                                          &info[count].info4, snum);
4392                         break;
4393                 case 5:
4394                         result = construct_printer_info5(info, info2,
4395                                                          servername,
4396                                                          &info[count].info5, snum);
4397                         break;
4398
4399                 default:
4400                         result = WERR_UNKNOWN_LEVEL;
4401                         goto out;
4402                 }
4403
4404                 if (!W_ERROR_IS_OK(result)) {
4405                         goto out;
4406                 }
4407
4408                 count++;
4409         }
4410
4411 out:
4412         if (W_ERROR_IS_OK(result)) {
4413                 *info_p = talloc_move(mem_ctx, &info);
4414                 *count_p = count;
4415         }
4416
4417         talloc_free(tmp_ctx);
4418
4419         return result;
4420 }
4421
4422 /********************************************************************
4423  * handle enumeration of printers at level 0
4424  ********************************************************************/
4425
4426 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4427                                   const struct auth_session_info *session_info,
4428                                   struct messaging_context *msg_ctx,
4429                                   uint32_t flags,
4430                                   const char *servername,
4431                                   union spoolss_PrinterInfo **info,
4432                                   uint32_t *count)
4433 {
4434         DEBUG(4,("enum_all_printers_info_0\n"));
4435
4436         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4437                                             servername, 0, flags, info, count);
4438 }
4439
4440
4441 /********************************************************************
4442 ********************************************************************/
4443
4444 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4445                                        const struct auth_session_info *session_info,
4446                                        struct messaging_context *msg_ctx,
4447                                        const char *servername,
4448                                        uint32_t flags,
4449                                        union spoolss_PrinterInfo **info,
4450                                        uint32_t *count)
4451 {
4452         DEBUG(4,("enum_all_printers_info_1\n"));
4453
4454         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4455                                             servername, 1, flags, info, count);
4456 }
4457
4458 /********************************************************************
4459  enum_all_printers_info_1_local.
4460 *********************************************************************/
4461
4462 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4463                                              const struct auth_session_info *session_info,
4464                                              struct messaging_context *msg_ctx,
4465                                              const char *servername,
4466                                              union spoolss_PrinterInfo **info,
4467                                              uint32_t *count)
4468 {
4469         DEBUG(4,("enum_all_printers_info_1_local\n"));
4470
4471         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4472                                         servername, PRINTER_ENUM_ICON8, info, count);
4473 }
4474
4475 /********************************************************************
4476  enum_all_printers_info_1_name.
4477 *********************************************************************/
4478
4479 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4480                                             const struct auth_session_info *session_info,
4481                                             struct messaging_context *msg_ctx,
4482                                             const char *servername,
4483                                             union spoolss_PrinterInfo **info,
4484                                             uint32_t *count)
4485 {
4486         const char *s = servername;
4487
4488         DEBUG(4,("enum_all_printers_info_1_name\n"));
4489
4490         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4491                 s = servername + 2;
4492         }
4493
4494         if (!is_myname_or_ipaddr(s)) {
4495                 return WERR_INVALID_NAME;
4496         }
4497
4498         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4499                                         servername, PRINTER_ENUM_ICON8, info, count);
4500 }
4501
4502 /********************************************************************
4503  enum_all_printers_info_1_network.
4504 *********************************************************************/
4505
4506 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4507                                                const struct auth_session_info *session_info,
4508                                                struct messaging_context *msg_ctx,
4509                                                const char *servername,
4510                                                union spoolss_PrinterInfo **info,
4511                                                uint32_t *count)
4512 {
4513         const char *s = servername;
4514
4515         DEBUG(4,("enum_all_printers_info_1_network\n"));
4516
4517         /* If we respond to a enum_printers level 1 on our name with flags
4518            set to PRINTER_ENUM_REMOTE with a list of printers then these
4519            printers incorrectly appear in the APW browse list.
4520            Specifically the printers for the server appear at the workgroup
4521            level where all the other servers in the domain are
4522            listed. Windows responds to this call with a
4523            WERR_CAN_NOT_COMPLETE so we should do the same. */
4524
4525         if (servername[0] == '\\' && servername[1] == '\\') {
4526                  s = servername + 2;
4527         }
4528
4529         if (is_myname_or_ipaddr(s)) {
4530                  return WERR_CAN_NOT_COMPLETE;
4531         }
4532
4533         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4534                                         servername, PRINTER_ENUM_NAME, info, count);
4535 }
4536
4537 /********************************************************************
4538  * api_spoolss_enumprinters
4539  *
4540  * called from api_spoolss_enumprinters (see this to understand)
4541  ********************************************************************/
4542
4543 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4544                                        const struct auth_session_info *session_info,
4545                                        struct messaging_context *msg_ctx,
4546                                        const char *servername,
4547                                        union spoolss_PrinterInfo **info,
4548                                        uint32_t *count)
4549 {
4550         DEBUG(4,("enum_all_printers_info_2\n"));
4551
4552         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4553                                             servername, 2, 0, info, count);
4554 }
4555
4556 /********************************************************************
4557  * handle enumeration of printers at level 1
4558  ********************************************************************/
4559
4560 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4561                                   const struct auth_session_info *session_info,
4562                                   struct messaging_context *msg_ctx,
4563                                   uint32_t flags,
4564                                   const char *servername,
4565                                   union spoolss_PrinterInfo **info,
4566                                   uint32_t *count)
4567 {
4568         /* Not all the flags are equals */
4569
4570         if (flags & PRINTER_ENUM_LOCAL) {
4571                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4572                                                       msg_ctx, servername, info, count);
4573         }
4574
4575         if (flags & PRINTER_ENUM_NAME) {
4576                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4577                                                      msg_ctx, servername, info,
4578                                                      count);
4579         }
4580
4581         if (flags & PRINTER_ENUM_NETWORK) {
4582                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4583                                                         msg_ctx, servername, info,
4584                                                         count);
4585         }
4586
4587         return WERR_OK; /* NT4sp5 does that */
4588 }
4589
4590 /********************************************************************
4591  * handle enumeration of printers at level 2
4592  ********************************************************************/
4593
4594 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4595                                   const struct auth_session_info *session_info,
4596                                   struct messaging_context *msg_ctx,
4597                                   uint32_t flags,
4598                                   const char *servername,
4599                                   union spoolss_PrinterInfo **info,
4600                                   uint32_t *count)
4601 {
4602         if (flags & PRINTER_ENUM_LOCAL) {
4603
4604                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4605                                                 servername,
4606                                                 info, count);
4607         }
4608
4609         if (flags & PRINTER_ENUM_NAME) {
4610                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4611                         return WERR_INVALID_NAME;
4612                 }
4613
4614                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4615                                                 servername,
4616                                                 info, count);
4617         }
4618
4619         if (flags & PRINTER_ENUM_REMOTE) {
4620                 return WERR_UNKNOWN_LEVEL;
4621         }
4622
4623         return WERR_OK;
4624 }
4625
4626 /********************************************************************
4627  * handle enumeration of printers at level 4
4628  ********************************************************************/
4629
4630 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4631                                   const struct auth_session_info *session_info,
4632                                   struct messaging_context *msg_ctx,
4633                                   uint32_t flags,
4634                                   const char *servername,
4635                                   union spoolss_PrinterInfo **info,
4636                                   uint32_t *count)
4637 {
4638         DEBUG(4,("enum_all_printers_info_4\n"));
4639
4640         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4641                                             servername, 4, flags, info, count);
4642 }
4643
4644
4645 /********************************************************************
4646  * handle enumeration of printers at level 5
4647  ********************************************************************/
4648
4649 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4650                                   const struct auth_session_info *session_info,
4651                                   struct messaging_context *msg_ctx,
4652                                   uint32_t flags,
4653                                   const char *servername,
4654                                   union spoolss_PrinterInfo **info,
4655                                   uint32_t *count)
4656 {
4657         DEBUG(4,("enum_all_printers_info_5\n"));
4658
4659         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4660                                             servername, 5, flags, info, count);
4661 }
4662
4663 /****************************************************************
4664  _spoolss_EnumPrinters
4665 ****************************************************************/
4666
4667 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4668                              struct spoolss_EnumPrinters *r)
4669 {
4670         const struct auth_session_info *session_info = get_session_info_system();
4671         WERROR result;
4672
4673         /* that's an [in out] buffer */
4674
4675         if (!r->in.buffer && (r->in.offered != 0)) {
4676                 return WERR_INVALID_PARAM;
4677         }
4678
4679         DEBUG(4,("_spoolss_EnumPrinters\n"));
4680
4681         *r->out.needed = 0;
4682         *r->out.count = 0;
4683         *r->out.info = NULL;
4684
4685         /*
4686          * Level 1:
4687          *          flags==PRINTER_ENUM_NAME
4688          *           if name=="" then enumerates all printers
4689          *           if name!="" then enumerate the printer
4690          *          flags==PRINTER_ENUM_REMOTE
4691          *          name is NULL, enumerate printers
4692          * Level 2: name!="" enumerates printers, name can't be NULL
4693          * Level 3: doesn't exist
4694          * Level 4: does a local registry lookup
4695          * Level 5: same as Level 2
4696          */
4697
4698         if (r->in.server && r->in.server[0] == '\0') {
4699                 r->in.server = NULL;
4700         }
4701
4702         switch (r->in.level) {
4703         case 0:
4704                 result = enumprinters_level0(p->mem_ctx, session_info,
4705                                              p->msg_ctx, r->in.flags,
4706                                              r->in.server,
4707                                              r->out.info, r->out.count);
4708                 break;
4709         case 1:
4710                 result = enumprinters_level1(p->mem_ctx, session_info,
4711                                              p->msg_ctx, r->in.flags,
4712                                              r->in.server,
4713                                              r->out.info, r->out.count);
4714                 break;
4715         case 2:
4716                 result = enumprinters_level2(p->mem_ctx, session_info,
4717                                              p->msg_ctx, r->in.flags,
4718                                              r->in.server,
4719                                              r->out.info, r->out.count);
4720                 break;
4721         case 4:
4722                 result = enumprinters_level4(p->mem_ctx, session_info,
4723                                              p->msg_ctx, r->in.flags,
4724                                              r->in.server,
4725                                              r->out.info, r->out.count);
4726                 break;
4727         case 5:
4728                 result = enumprinters_level5(p->mem_ctx, session_info,
4729                                              p->msg_ctx, r->in.flags,
4730                                              r->in.server,
4731                                              r->out.info, r->out.count);
4732                 break;
4733         default:
4734                 return WERR_UNKNOWN_LEVEL;
4735         }
4736
4737         if (!W_ERROR_IS_OK(result)) {
4738                 return result;
4739         }
4740
4741         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4742                                                      spoolss_EnumPrinters,
4743                                                      *r->out.info, r->in.level,
4744                                                      *r->out.count);
4745         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4746         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4747
4748         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4749 }
4750
4751 /****************************************************************
4752  _spoolss_GetPrinter
4753 ****************************************************************/
4754
4755 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4756                            struct spoolss_GetPrinter *r)
4757 {
4758         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4759         struct spoolss_PrinterInfo2 *info2 = NULL;
4760         WERROR result = WERR_OK;
4761         int snum;
4762
4763         /* that's an [in out] buffer */
4764
4765         if (!r->in.buffer && (r->in.offered != 0)) {
4766                 return WERR_INVALID_PARAM;
4767         }
4768
4769         *r->out.needed = 0;
4770
4771         if (Printer == NULL) {
4772                 return WERR_BADFID;
4773         }
4774
4775         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4776                 return WERR_BADFID;
4777         }
4778
4779         result = winreg_get_printer_internal(p->mem_ctx,
4780                                     get_session_info_system(),
4781                                     p->msg_ctx,
4782                                     lp_const_servicename(snum),
4783                                     &info2);
4784         if (!W_ERROR_IS_OK(result)) {
4785                 goto out;
4786         }
4787
4788         switch (r->in.level) {
4789         case 0:
4790                 result = construct_printer_info0(p->mem_ctx,
4791                                                  get_session_info_system(),
4792                                                  p->msg_ctx,
4793                                                  info2,
4794                                                  Printer->servername,
4795                                                  &r->out.info->info0,
4796                                                  snum);
4797                 break;
4798         case 1:
4799                 result = construct_printer_info1(p->mem_ctx, info2,
4800                                                  PRINTER_ENUM_ICON8,
4801                                                  Printer->servername,
4802                                                  &r->out.info->info1, snum);
4803                 break;
4804         case 2:
4805                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4806                                                  Printer->servername,
4807                                                  &r->out.info->info2, snum);
4808                 break;
4809         case 3:
4810                 result = construct_printer_info3(p->mem_ctx, info2,
4811                                                  Printer->servername,
4812                                                  &r->out.info->info3, snum);
4813                 break;
4814         case 4:
4815                 result = construct_printer_info4(p->mem_ctx, info2,
4816                                                  Printer->servername,
4817                                                  &r->out.info->info4, snum);
4818                 break;
4819         case 5:
4820                 result = construct_printer_info5(p->mem_ctx, info2,
4821                                                  Printer->servername,
4822                                                  &r->out.info->info5, snum);
4823                 break;
4824         case 6:
4825                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4826                                                  Printer->servername,
4827                                                  &r->out.info->info6, snum);
4828                 break;
4829         case 7:
4830                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4831                                                  Printer->servername,
4832                                                  &r->out.info->info7, snum);
4833                 break;
4834         case 8:
4835                 result = construct_printer_info8(p->mem_ctx, info2,
4836                                                  Printer->servername,
4837                                                  &r->out.info->info8, snum);
4838                 break;
4839         default:
4840                 result = WERR_UNKNOWN_LEVEL;
4841                 break;
4842         }
4843         TALLOC_FREE(info2);
4844
4845  out:
4846         if (!W_ERROR_IS_OK(result)) {
4847                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4848                           r->in.level, win_errstr(result)));
4849                 TALLOC_FREE(r->out.info);
4850                 return result;
4851         }
4852
4853         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4854                                                r->out.info, r->in.level);
4855         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4856
4857         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4858 }
4859
4860 /********************************************************************
4861  ********************************************************************/
4862
4863 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4864         do { \
4865                 if (in && strlen(in)) { \
4866                         out = talloc_strdup(mem_ctx, in); \
4867                 } else { \
4868                         out = talloc_strdup(mem_ctx, ""); \
4869                 } \
4870                 W_ERROR_HAVE_NO_MEMORY(out); \
4871         } while (0);
4872
4873 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4874         do { \
4875                 if (in && strlen(in)) { \
4876                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4877                 } else { \
4878                         out = talloc_strdup(mem_ctx, ""); \
4879                 } \
4880                 W_ERROR_HAVE_NO_MEMORY(out); \
4881         } while (0);
4882
4883 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4884                                                   const char **string_array,
4885                                                   const char ***presult,
4886                                                   const char *cservername,
4887                                                   const char *arch,
4888                                                   int version)
4889 {
4890         int i, num_strings = 0;
4891         const char **array = NULL;
4892
4893         if (string_array == NULL) {
4894                 return WERR_INVALID_PARAMETER;
4895         }
4896
4897         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4898                 const char *str = NULL;
4899
4900                 if (cservername == NULL || arch == NULL) {
4901                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4902                 } else {
4903                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4904                 }
4905
4906                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4907                         TALLOC_FREE(array);
4908                         return WERR_NOMEM;
4909                 }
4910         }
4911
4912         if (i > 0) {
4913                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4914                              &array, &num_strings);
4915         }
4916
4917         if (presult) {
4918                 *presult = array;
4919         }
4920
4921         return WERR_OK;
4922 }
4923
4924 /********************************************************************
4925  * fill a spoolss_DriverInfo1 struct
4926  ********************************************************************/
4927
4928 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4929                                         struct spoolss_DriverInfo1 *r,
4930                                         const struct spoolss_DriverInfo8 *driver,
4931                                         const char *servername)
4932 {
4933         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4934         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4935
4936         return WERR_OK;
4937 }
4938
4939 /********************************************************************
4940  * fill a spoolss_DriverInfo2 struct
4941  ********************************************************************/
4942
4943 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4944                                         struct spoolss_DriverInfo2 *r,
4945                                         const struct spoolss_DriverInfo8 *driver,
4946                                         const char *servername)
4947
4948 {
4949         const char *cservername = canon_servername(servername);
4950
4951         r->version              = driver->version;
4952
4953         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4954         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4955         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4956         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4957
4958         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4959                                driver->architecture,
4960                                driver->version,
4961                                driver->driver_path,
4962                                r->driver_path);
4963
4964         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4965                                driver->architecture,
4966                                driver->version,
4967                                driver->data_file,
4968                                r->data_file);
4969
4970         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4971                                driver->architecture,
4972                                driver->version,
4973                                driver->config_file,
4974                                r->config_file);
4975
4976         return WERR_OK;
4977 }
4978
4979 /********************************************************************
4980  * fill a spoolss_DriverInfo3 struct
4981  ********************************************************************/
4982
4983 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4984                                         struct spoolss_DriverInfo3 *r,
4985                                         const struct spoolss_DriverInfo8 *driver,
4986                                         const char *servername)
4987 {
4988         const char *cservername = canon_servername(servername);
4989
4990         r->version              = driver->version;
4991
4992         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4993         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4994         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4995         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4996
4997         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4998                                driver->architecture,
4999                                driver->version,
5000                                driver->driver_path,
5001                                r->driver_path);
5002
5003         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5004                                driver->architecture,
5005                                driver->version,
5006                                driver->data_file,
5007                                r->data_file);
5008
5009         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5010                                driver->architecture,
5011                                driver->version,
5012                                driver->config_file,
5013                                r->config_file);
5014
5015         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5016                                driver->architecture,
5017                                driver->version,
5018                                driver->help_file,
5019                                r->help_file);
5020
5021         FILL_DRIVER_STRING(mem_ctx,
5022                            driver->monitor_name,
5023                            r->monitor_name);
5024
5025         FILL_DRIVER_STRING(mem_ctx,
5026                            driver->default_datatype,
5027                            r->default_datatype);
5028
5029         return string_array_from_driver_info(mem_ctx,
5030                                              driver->dependent_files,
5031                                              &r->dependent_files,
5032                                              cservername,
5033                                              driver->architecture,
5034                                              driver->version);
5035 }
5036
5037 /********************************************************************
5038  * fill a spoolss_DriverInfo4 struct
5039  ********************************************************************/
5040
5041 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5042                                         struct spoolss_DriverInfo4 *r,
5043                                         const struct spoolss_DriverInfo8 *driver,
5044                                         const char *servername)
5045 {
5046         const char *cservername = canon_servername(servername);
5047         WERROR result;
5048
5049         r->version              = driver->version;
5050
5051         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5052         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5053         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5054         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5055
5056         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5057                                driver->architecture,
5058                                driver->version,
5059                                driver->driver_path,
5060                                r->driver_path);
5061
5062         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5063                                driver->architecture,
5064                                driver->version,
5065                                driver->data_file,
5066                                r->data_file);
5067
5068         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5069                                driver->architecture,
5070                                driver->version,
5071                                driver->config_file,
5072                                r->config_file);
5073
5074         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5075                                driver->architecture,
5076                                driver->version,
5077                                driver->help_file,
5078                                r->help_file);
5079
5080         result = string_array_from_driver_info(mem_ctx,
5081                                                driver->dependent_files,
5082                                                &r->dependent_files,
5083                                                cservername,
5084                                                driver->architecture,
5085                                                driver->version);
5086         if (!W_ERROR_IS_OK(result)) {
5087                 return result;
5088         }
5089
5090         FILL_DRIVER_STRING(mem_ctx,
5091                            driver->monitor_name,
5092                            r->monitor_name);
5093
5094         FILL_DRIVER_STRING(mem_ctx,
5095                            driver->default_datatype,
5096                            r->default_datatype);
5097
5098
5099         result = string_array_from_driver_info(mem_ctx,
5100                                                driver->previous_names,
5101                                                &r->previous_names,
5102                                                NULL, NULL, 0);
5103
5104         return result;
5105 }
5106
5107 /********************************************************************
5108  * fill a spoolss_DriverInfo5 struct
5109  ********************************************************************/
5110
5111 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5112                                         struct spoolss_DriverInfo5 *r,
5113                                         const struct spoolss_DriverInfo8 *driver,
5114                                         const char *servername)
5115 {
5116         const char *cservername = canon_servername(servername);
5117
5118         r->version              = driver->version;
5119
5120         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5121         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5122         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5123         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5124
5125         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5126                                driver->architecture,
5127                                driver->version,
5128                                driver->driver_path,
5129                                r->driver_path);
5130
5131         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5132                                driver->architecture,
5133                                driver->version,
5134                                driver->data_file,
5135                                r->data_file);
5136
5137         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5138                                driver->architecture,
5139                                driver->version,
5140                                driver->config_file,
5141                                r->config_file);
5142
5143         r->driver_attributes    = 0;
5144         r->config_version       = 0;
5145         r->driver_version       = 0;
5146
5147         return WERR_OK;
5148 }
5149 /********************************************************************
5150  * fill a spoolss_DriverInfo6 struct
5151  ********************************************************************/
5152
5153 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5154                                         struct spoolss_DriverInfo6 *r,
5155                                         const struct spoolss_DriverInfo8 *driver,
5156                                         const char *servername)
5157 {
5158         const char *cservername = canon_servername(servername);
5159         WERROR result;
5160
5161         r->version              = driver->version;
5162
5163         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5164         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5165         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5166         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5167
5168         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5169                                driver->architecture,
5170                                driver->version,
5171                                driver->driver_path,
5172                                r->driver_path);
5173
5174         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5175                                driver->architecture,
5176                                driver->version,
5177                                driver->data_file,
5178                                r->data_file);
5179
5180         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5181                                driver->architecture,
5182                                driver->version,
5183                                driver->config_file,
5184                                r->config_file);
5185
5186         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5187                                driver->architecture,
5188                                driver->version,
5189                                driver->help_file,
5190                                r->help_file);
5191
5192         FILL_DRIVER_STRING(mem_ctx,
5193                            driver->monitor_name,
5194                            r->monitor_name);
5195
5196         FILL_DRIVER_STRING(mem_ctx,
5197                            driver->default_datatype,
5198                            r->default_datatype);
5199
5200         result = string_array_from_driver_info(mem_ctx,
5201                                                driver->dependent_files,
5202                                                &r->dependent_files,
5203                                                cservername,
5204                                                driver->architecture,
5205                                                driver->version);
5206         if (!W_ERROR_IS_OK(result)) {
5207                 return result;
5208         }
5209
5210         result = string_array_from_driver_info(mem_ctx,
5211                                                driver->previous_names,
5212                                                &r->previous_names,
5213                                                NULL, NULL, 0);
5214         if (!W_ERROR_IS_OK(result)) {
5215                 return result;
5216         }
5217
5218         r->driver_date          = driver->driver_date;
5219         r->driver_version       = driver->driver_version;
5220
5221         FILL_DRIVER_STRING(mem_ctx,
5222                            driver->manufacturer_name,
5223                            r->manufacturer_name);
5224         FILL_DRIVER_STRING(mem_ctx,
5225                            driver->manufacturer_url,
5226                            r->manufacturer_url);
5227         FILL_DRIVER_STRING(mem_ctx,
5228                            driver->hardware_id,
5229                            r->hardware_id);
5230         FILL_DRIVER_STRING(mem_ctx,
5231                            driver->provider,
5232                            r->provider);
5233
5234         return WERR_OK;
5235 }
5236
5237 /********************************************************************
5238  * fill a spoolss_DriverInfo8 struct
5239  ********************************************************************/
5240
5241 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5242                                         struct spoolss_DriverInfo8 *r,
5243                                         const struct spoolss_DriverInfo8 *driver,
5244                                         const char *servername)
5245 {
5246         const char *cservername = canon_servername(servername);
5247         WERROR result;
5248
5249         r->version              = driver->version;
5250
5251         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5252         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5253         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5254         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5255
5256         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5257                                driver->architecture,
5258                                driver->version,
5259                                driver->driver_path,
5260                                r->driver_path);
5261
5262         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5263                                driver->architecture,
5264                                driver->version,
5265                                driver->data_file,
5266                                r->data_file);
5267
5268         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5269                                driver->architecture,
5270                                driver->version,
5271                                driver->config_file,
5272                                r->config_file);
5273
5274         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5275                                driver->architecture,
5276                                driver->version,
5277                                driver->help_file,
5278                                r->help_file);
5279
5280         FILL_DRIVER_STRING(mem_ctx,
5281                            driver->monitor_name,
5282                            r->monitor_name);
5283
5284         FILL_DRIVER_STRING(mem_ctx,
5285                            driver->default_datatype,
5286                            r->default_datatype);
5287
5288         result = string_array_from_driver_info(mem_ctx,
5289                                                driver->dependent_files,
5290                                                &r->dependent_files,
5291                                                cservername,
5292                                                driver->architecture,
5293                                                driver->version);
5294         if (!W_ERROR_IS_OK(result)) {
5295                 return result;
5296         }
5297
5298         result = string_array_from_driver_info(mem_ctx,
5299                                                driver->previous_names,
5300                                                &r->previous_names,
5301                                                NULL, NULL, 0);
5302         if (!W_ERROR_IS_OK(result)) {
5303                 return result;
5304         }
5305
5306         r->driver_date          = driver->driver_date;
5307         r->driver_version       = driver->driver_version;
5308
5309         FILL_DRIVER_STRING(mem_ctx,
5310                            driver->manufacturer_name,
5311                            r->manufacturer_name);
5312         FILL_DRIVER_STRING(mem_ctx,
5313                            driver->manufacturer_url,
5314                            r->manufacturer_url);
5315         FILL_DRIVER_STRING(mem_ctx,
5316                            driver->hardware_id,
5317                            r->hardware_id);
5318         FILL_DRIVER_STRING(mem_ctx,
5319                            driver->provider,
5320                            r->provider);
5321
5322         FILL_DRIVER_STRING(mem_ctx,
5323                            driver->print_processor,
5324                            r->print_processor);
5325         FILL_DRIVER_STRING(mem_ctx,
5326                            driver->vendor_setup,
5327                            r->vendor_setup);
5328
5329         result = string_array_from_driver_info(mem_ctx,
5330                                                driver->color_profiles,
5331                                                &r->color_profiles,
5332                                                NULL, NULL, 0);
5333         if (!W_ERROR_IS_OK(result)) {
5334                 return result;
5335         }
5336
5337         FILL_DRIVER_STRING(mem_ctx,
5338                            driver->inf_path,
5339                            r->inf_path);
5340
5341         r->printer_driver_attributes    = driver->printer_driver_attributes;
5342
5343         result = string_array_from_driver_info(mem_ctx,
5344                                                driver->core_driver_dependencies,
5345                                                &r->core_driver_dependencies,
5346                                                NULL, NULL, 0);
5347         if (!W_ERROR_IS_OK(result)) {
5348                 return result;
5349         }
5350
5351         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5352         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5353
5354         return WERR_OK;
5355 }
5356
5357 #if 0 /* disabled until marshalling issues are resolved - gd */
5358 /********************************************************************
5359  ********************************************************************/
5360
5361 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5362                                           struct spoolss_DriverFileInfo *r,
5363                                           const char *cservername,
5364                                           const char *file_name,
5365                                           enum spoolss_DriverFileType file_type,
5366                                           uint32_t file_version)
5367 {
5368         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5369                                           cservername, file_name);
5370         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5371         r->file_type    = file_type;
5372         r->file_version = file_version;
5373
5374         return WERR_OK;
5375 }
5376
5377 /********************************************************************
5378  ********************************************************************/
5379
5380 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5381                                                  const struct spoolss_DriverInfo8 *driver,
5382                                                  const char *cservername,
5383                                                  struct spoolss_DriverFileInfo **info_p,
5384                                                  uint32_t *count_p)
5385 {
5386         struct spoolss_DriverFileInfo *info = NULL;
5387         uint32_t count = 0;
5388         WERROR result;
5389         uint32_t i;
5390
5391         *info_p = NULL;
5392         *count_p = 0;
5393
5394         if (strlen(driver->driver_path)) {
5395                 info = talloc_realloc(mem_ctx, info,
5396                                             struct spoolss_DriverFileInfo,
5397                                             count + 1);
5398                 W_ERROR_HAVE_NO_MEMORY(info);
5399                 result = fill_spoolss_DriverFileInfo(info,
5400                                                      &info[count],
5401                                                      cservername,
5402                                                      driver->driver_path,
5403                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5404                                                      0);
5405                 W_ERROR_NOT_OK_RETURN(result);
5406                 count++;
5407         }
5408
5409         if (strlen(driver->config_file)) {
5410                 info = talloc_realloc(mem_ctx, info,
5411                                             struct spoolss_DriverFileInfo,
5412                                             count + 1);
5413                 W_ERROR_HAVE_NO_MEMORY(info);
5414                 result = fill_spoolss_DriverFileInfo(info,
5415                                                      &info[count],
5416                                                      cservername,
5417                                                      driver->config_file,
5418                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5419                                                      0);
5420                 W_ERROR_NOT_OK_RETURN(result);
5421                 count++;
5422         }
5423
5424         if (strlen(driver->data_file)) {
5425                 info = talloc_realloc(mem_ctx, info,
5426                                             struct spoolss_DriverFileInfo,
5427                                             count + 1);
5428                 W_ERROR_HAVE_NO_MEMORY(info);
5429                 result = fill_spoolss_DriverFileInfo(info,
5430                                                      &info[count],
5431                                                      cservername,
5432                                                      driver->data_file,
5433                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5434                                                      0);
5435                 W_ERROR_NOT_OK_RETURN(result);
5436                 count++;
5437         }
5438
5439         if (strlen(driver->help_file)) {
5440                 info = talloc_realloc(mem_ctx, info,
5441                                             struct spoolss_DriverFileInfo,
5442                                             count + 1);
5443                 W_ERROR_HAVE_NO_MEMORY(info);
5444                 result = fill_spoolss_DriverFileInfo(info,
5445                                                      &info[count],
5446                                                      cservername,
5447                                                      driver->help_file,
5448                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5449                                                      0);
5450                 W_ERROR_NOT_OK_RETURN(result);
5451                 count++;
5452         }
5453
5454         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5455                 info = talloc_realloc(mem_ctx, info,
5456                                             struct spoolss_DriverFileInfo,
5457                                             count + 1);
5458                 W_ERROR_HAVE_NO_MEMORY(info);
5459                 result = fill_spoolss_DriverFileInfo(info,
5460                                                      &info[count],
5461                                                      cservername,
5462                                                      driver->dependent_files[i],
5463                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5464                                                      0);
5465                 W_ERROR_NOT_OK_RETURN(result);
5466                 count++;
5467         }
5468
5469         *info_p = info;
5470         *count_p = count;
5471
5472         return WERR_OK;
5473 }
5474
5475 /********************************************************************
5476  * fill a spoolss_DriverInfo101 struct
5477  ********************************************************************/
5478
5479 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5480                                           struct spoolss_DriverInfo101 *r,
5481                                           const struct spoolss_DriverInfo8 *driver,
5482                                           const char *servername)
5483 {
5484         const char *cservername = canon_servername(servername);
5485         WERROR result;
5486
5487         r->version              = driver->version;
5488
5489         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5490         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5491         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5492         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5493
5494         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5495                                                     cservername,
5496                                                     &r->file_info,
5497                                                     &r->file_count);
5498         if (!W_ERROR_IS_OK(result)) {
5499                 return result;
5500         }
5501
5502         FILL_DRIVER_STRING(mem_ctx,
5503                            driver->monitor_name,
5504                            r->monitor_name);
5505
5506         FILL_DRIVER_STRING(mem_ctx,
5507                            driver->default_datatype,
5508                            r->default_datatype);
5509
5510         result = string_array_from_driver_info(mem_ctx,
5511                                                driver->previous_names,
5512                                                &r->previous_names,
5513                                                NULL, NULL, 0);
5514         if (!W_ERROR_IS_OK(result)) {
5515                 return result;
5516         }
5517
5518         r->driver_date          = driver->driver_date;
5519         r->driver_version       = driver->driver_version;
5520
5521         FILL_DRIVER_STRING(mem_ctx,
5522                            driver->manufacturer_name,
5523                            r->manufacturer_name);
5524         FILL_DRIVER_STRING(mem_ctx,
5525                            driver->manufacturer_url,
5526                            r->manufacturer_url);
5527         FILL_DRIVER_STRING(mem_ctx,
5528                            driver->hardware_id,
5529                            r->hardware_id);
5530         FILL_DRIVER_STRING(mem_ctx,
5531                            driver->provider,
5532                            r->provider);
5533
5534         return WERR_OK;
5535 }
5536 #endif
5537 /********************************************************************
5538  ********************************************************************/
5539
5540 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5541                                                   const struct auth_session_info *session_info,
5542                                                   struct messaging_context *msg_ctx,
5543                                                   uint32_t level,
5544                                                   union spoolss_DriverInfo *r,
5545                                                   int snum,
5546                                                   const char *servername,
5547                                                   const char *architecture,
5548                                                   uint32_t version)
5549 {
5550         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5551         struct spoolss_DriverInfo8 *driver;
5552         WERROR result;
5553         struct dcerpc_binding_handle *b;
5554         TALLOC_CTX *tmp_ctx = NULL;
5555
5556         if (level == 101) {
5557                 return WERR_UNKNOWN_LEVEL;
5558         }
5559
5560         tmp_ctx = talloc_new(mem_ctx);
5561         if (!tmp_ctx) {
5562                 return WERR_NOMEM;
5563         }
5564
5565         result = winreg_printer_binding_handle(tmp_ctx,
5566                                                session_info,
5567                                                msg_ctx,
5568                                                &b);
5569         if (!W_ERROR_IS_OK(result)) {
5570                 goto done;
5571         }
5572
5573         result = winreg_get_printer(tmp_ctx, b,
5574                                     lp_const_servicename(snum),
5575                                     &pinfo2);
5576
5577         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5578                 win_errstr(result)));
5579
5580         if (!W_ERROR_IS_OK(result)) {
5581                 result = WERR_INVALID_PRINTER_NAME;
5582                 goto done;
5583         }
5584
5585         result = winreg_get_driver(tmp_ctx, b,
5586                                    architecture,
5587                                    pinfo2->drivername, version, &driver);
5588
5589         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5590                 win_errstr(result)));
5591
5592         if (!W_ERROR_IS_OK(result)) {
5593                 /*
5594                  * Is this a W2k client ?
5595                  */
5596
5597                 if (version < 3) {
5598                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5599                         goto done;
5600                 }
5601
5602                 /* Yes - try again with a WinNT driver. */
5603                 version = 2;
5604                 result = winreg_get_driver(tmp_ctx, b,
5605                                            architecture,
5606                                            pinfo2->drivername,
5607                                            version, &driver);
5608                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5609                         win_errstr(result)));
5610                 if (!W_ERROR_IS_OK(result)) {
5611                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5612                         goto done;
5613                 }
5614         }
5615
5616         /* these are allocated on mem_ctx and not tmp_ctx because they are
5617          * the 'return value' and need to utlive this call */
5618         switch (level) {
5619         case 1:
5620                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5621                 break;
5622         case 2:
5623                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5624                 break;
5625         case 3:
5626                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5627                 break;
5628         case 4:
5629                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5630                 break;
5631         case 5:
5632                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5633                 break;
5634         case 6:
5635                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5636                 break;
5637         case 8:
5638                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5639                 break;
5640 #if 0 /* disabled until marshalling issues are resolved - gd */
5641         case 101:
5642                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5643                 break;
5644 #endif
5645         default:
5646                 result = WERR_UNKNOWN_LEVEL;
5647                 break;
5648         }
5649
5650 done:
5651         talloc_free(tmp_ctx);
5652         return result;
5653 }
5654
5655 /****************************************************************
5656  _spoolss_GetPrinterDriver2
5657 ****************************************************************/
5658
5659 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5660                                   struct spoolss_GetPrinterDriver2 *r)
5661 {
5662         struct printer_handle *printer;
5663         WERROR result;
5664
5665         int snum;
5666
5667         /* that's an [in out] buffer */
5668
5669         if (!r->in.buffer && (r->in.offered != 0)) {
5670                 return WERR_INVALID_PARAM;
5671         }
5672
5673         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5674
5675         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5676                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5677                 return WERR_INVALID_PRINTER_NAME;
5678         }
5679
5680         *r->out.needed = 0;
5681         *r->out.server_major_version = 0;
5682         *r->out.server_minor_version = 0;
5683
5684         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5685                 return WERR_BADFID;
5686         }
5687
5688         result = construct_printer_driver_info_level(p->mem_ctx,
5689                                                      get_session_info_system(),
5690                                                      p->msg_ctx,
5691                                                      r->in.level, r->out.info,
5692                                                      snum, printer->servername,
5693                                                      r->in.architecture,
5694                                                      r->in.client_major_version);
5695         if (!W_ERROR_IS_OK(result)) {
5696                 TALLOC_FREE(r->out.info);
5697                 return result;
5698         }
5699
5700         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5701                                                r->out.info, r->in.level);
5702         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5703
5704         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5705 }
5706
5707
5708 /****************************************************************
5709  _spoolss_StartPagePrinter
5710 ****************************************************************/
5711
5712 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5713                                  struct spoolss_StartPagePrinter *r)
5714 {
5715         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5716
5717         if (!Printer) {
5718                 DEBUG(3,("_spoolss_StartPagePrinter: "
5719                         "Error in startpageprinter printer handle\n"));
5720                 return WERR_BADFID;
5721         }
5722
5723         Printer->page_started = true;
5724         return WERR_OK;
5725 }
5726
5727 /****************************************************************
5728  _spoolss_EndPagePrinter
5729 ****************************************************************/
5730
5731 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5732                                struct spoolss_EndPagePrinter *r)
5733 {
5734         int snum;
5735
5736         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5737
5738         if (!Printer) {
5739                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5740                         OUR_HANDLE(r->in.handle)));
5741                 return WERR_BADFID;
5742         }
5743
5744         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5745                 return WERR_BADFID;
5746
5747         Printer->page_started = false;
5748         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5749
5750         return WERR_OK;
5751 }
5752
5753 /****************************************************************
5754  _spoolss_StartDocPrinter
5755 ****************************************************************/
5756
5757 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5758                                 struct spoolss_StartDocPrinter *r)
5759 {
5760         struct spoolss_DocumentInfo1 *info_1;
5761         int snum;
5762         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5763         WERROR werr;
5764         char *rhost;
5765         int rc;
5766
5767         if (!Printer) {
5768                 DEBUG(2,("_spoolss_StartDocPrinter: "
5769                         "Invalid handle (%s:%u:%u)\n",
5770                         OUR_HANDLE(r->in.handle)));
5771                 return WERR_BADFID;
5772         }
5773
5774         if (Printer->jobid) {
5775                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5776                           "StartDocPrinter called twice! "
5777                           "(existing jobid = %d)\n", Printer->jobid));
5778                 return WERR_INVALID_HANDLE;
5779         }
5780
5781         if (r->in.level != 1) {
5782                 return WERR_UNKNOWN_LEVEL;
5783         }
5784
5785         info_1 = r->in.info.info1;
5786
5787         /*
5788          * a nice thing with NT is it doesn't listen to what you tell it.
5789          * when asked to send _only_ RAW datas, it tries to send datas
5790          * in EMF format.
5791          *
5792          * So I add checks like in NT Server ...
5793          */
5794
5795         if (info_1->datatype) {
5796                 if (strcmp(info_1->datatype, "RAW") != 0) {
5797                         *r->out.job_id = 0;
5798                         return WERR_INVALID_DATATYPE;
5799                 }
5800         }
5801
5802         /* get the share number of the printer */
5803         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5804                 return WERR_BADFID;
5805         }
5806
5807         rc = get_remote_hostname(p->remote_address,
5808                                  &rhost,
5809                                  p->mem_ctx);
5810         if (rc < 0) {
5811                 return WERR_NOMEM;
5812         }
5813         if (strequal(rhost,"UNKNOWN")) {
5814                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5815                                                          p->mem_ctx);
5816                 if (rhost == NULL) {
5817                         return WERR_NOMEM;
5818                 }
5819         }
5820
5821         werr = print_job_start(p->session_info,
5822                                p->msg_ctx,
5823                                rhost,
5824                                snum,
5825                                info_1->document_name,
5826                                info_1->output_file,
5827                                Printer->devmode,
5828                                &Printer->jobid);
5829
5830         /* An error occured in print_job_start() so return an appropriate
5831            NT error code. */
5832
5833         if (!W_ERROR_IS_OK(werr)) {
5834                 return werr;
5835         }
5836
5837         Printer->document_started = true;
5838         *r->out.job_id = Printer->jobid;
5839
5840         return WERR_OK;
5841 }
5842
5843 /****************************************************************
5844  _spoolss_EndDocPrinter
5845 ****************************************************************/
5846
5847 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5848                               struct spoolss_EndDocPrinter *r)
5849 {
5850         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5851         NTSTATUS status;
5852         int snum;
5853
5854         if (!Printer) {
5855                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5856                         OUR_HANDLE(r->in.handle)));
5857                 return WERR_BADFID;
5858         }
5859
5860         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5861                 return WERR_BADFID;
5862         }
5863
5864         Printer->document_started = false;
5865         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5866         if (!NT_STATUS_IS_OK(status)) {
5867                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5868                           "print_job_end failed [%s]\n",
5869                           nt_errstr(status)));
5870         }
5871
5872         Printer->jobid = 0;
5873         return ntstatus_to_werror(status);
5874 }
5875
5876 /****************************************************************
5877  _spoolss_WritePrinter
5878 ****************************************************************/
5879
5880 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5881                              struct spoolss_WritePrinter *r)
5882 {
5883         ssize_t buffer_written;
5884         int snum;
5885         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5886
5887         if (!Printer) {
5888                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5889                         OUR_HANDLE(r->in.handle)));
5890                 *r->out.num_written = r->in._data_size;
5891                 return WERR_BADFID;
5892         }
5893
5894         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5895                 return WERR_BADFID;
5896
5897         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5898         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5899                                                    snum, Printer->jobid,
5900                                                    (const char *)r->in.data.data,
5901                                                    (size_t)r->in._data_size);
5902         if (buffer_written == (ssize_t)-1) {
5903                 *r->out.num_written = 0;
5904                 if (errno == ENOSPC)
5905                         return WERR_NO_SPOOL_SPACE;
5906                 else
5907                         return WERR_ACCESS_DENIED;
5908         }
5909
5910         *r->out.num_written = r->in._data_size;
5911
5912         return WERR_OK;
5913 }
5914
5915 /********************************************************************
5916  * api_spoolss_getprinter
5917  * called from the spoolss dispatcher
5918  *
5919  ********************************************************************/
5920
5921 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5922                               struct pipes_struct *p)
5923 {
5924         const struct auth_session_info *session_info = p->session_info;
5925         int snum;
5926         WERROR errcode = WERR_BADFUNC;
5927         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5928
5929         if (!Printer) {
5930                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5931                         OUR_HANDLE(handle)));
5932                 return WERR_BADFID;
5933         }
5934
5935         if (!get_printer_snum(p, handle, &snum, NULL))
5936                 return WERR_BADFID;
5937
5938         switch (command) {
5939         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5940                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5941                 break;
5942         case SPOOLSS_PRINTER_CONTROL_RESUME:
5943         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5944                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5945                 break;
5946         case SPOOLSS_PRINTER_CONTROL_PURGE:
5947                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5948                 break;
5949         default:
5950                 return WERR_UNKNOWN_LEVEL;
5951         }
5952
5953         return errcode;
5954 }
5955
5956
5957 /****************************************************************
5958  _spoolss_AbortPrinter
5959  * From MSDN: "Deletes printer's spool file if printer is configured
5960  * for spooling"
5961 ****************************************************************/
5962
5963 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5964                              struct spoolss_AbortPrinter *r)
5965 {
5966         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5967         int             snum;
5968         WERROR          errcode = WERR_OK;
5969
5970         if (!Printer) {
5971                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5972                         OUR_HANDLE(r->in.handle)));
5973                 return WERR_BADFID;
5974         }
5975
5976         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5977                 return WERR_BADFID;
5978
5979         if (!Printer->document_started) {
5980                 return WERR_SPL_NO_STARTDOC;
5981         }
5982
5983         errcode = print_job_delete(p->session_info,
5984                                    p->msg_ctx,
5985                                    snum,
5986                                    Printer->jobid);
5987
5988         return errcode;
5989 }
5990
5991 /********************************************************************
5992  * called by spoolss_api_setprinter
5993  * when updating a printer description
5994  ********************************************************************/
5995
5996 static WERROR update_printer_sec(struct policy_handle *handle,
5997                                  struct pipes_struct *p,
5998                                  struct sec_desc_buf *secdesc_ctr)
5999 {
6000         struct spoolss_security_descriptor *new_secdesc = NULL;
6001         struct spoolss_security_descriptor *old_secdesc = NULL;
6002         const char *printer;
6003         WERROR result;
6004         int snum;
6005         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6006         struct dcerpc_binding_handle *b;
6007         TALLOC_CTX *tmp_ctx = NULL;
6008
6009         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6010                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6011                          OUR_HANDLE(handle)));
6012
6013                 result = WERR_BADFID;
6014                 goto done;
6015         }
6016
6017         if (secdesc_ctr == NULL) {
6018                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6019                 result = WERR_INVALID_PARAM;
6020                 goto done;
6021         }
6022         printer = lp_const_servicename(snum);
6023
6024         /* Check the user has permissions to change the security
6025            descriptor.  By experimentation with two NT machines, the user
6026            requires Full Access to the printer to change security
6027            information. */
6028
6029         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6030                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6031                 result = WERR_ACCESS_DENIED;
6032                 goto done;
6033         }
6034
6035         tmp_ctx = talloc_new(p->mem_ctx);
6036         if (!tmp_ctx) {
6037                 return WERR_NOMEM;
6038         }
6039
6040         result = winreg_printer_binding_handle(tmp_ctx,
6041                                                get_session_info_system(),
6042                                                p->msg_ctx,
6043                                                &b);
6044         if (!W_ERROR_IS_OK(result)) {
6045                 goto done;
6046         }
6047
6048         /* NT seems to like setting the security descriptor even though
6049            nothing may have actually changed. */
6050         result = winreg_get_printer_secdesc(tmp_ctx, b,
6051                                             printer,
6052                                             &old_secdesc);
6053         if (!W_ERROR_IS_OK(result)) {
6054                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6055                 result = WERR_BADFID;
6056                 goto done;
6057         }
6058
6059         if (DEBUGLEVEL >= 10) {
6060                 struct security_acl *the_acl;
6061                 int i;
6062
6063                 the_acl = old_secdesc->dacl;
6064                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6065                            printer, the_acl->num_aces));
6066
6067                 for (i = 0; i < the_acl->num_aces; i++) {
6068                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6069                                            &the_acl->aces[i].trustee),
6070                                   the_acl->aces[i].access_mask));
6071                 }
6072
6073                 the_acl = secdesc_ctr->sd->dacl;
6074
6075                 if (the_acl) {
6076                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6077                                    printer, the_acl->num_aces));
6078
6079                         for (i = 0; i < the_acl->num_aces; i++) {
6080                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6081                                                    &the_acl->aces[i].trustee),
6082                                            the_acl->aces[i].access_mask));
6083                         }
6084                 } else {
6085                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6086                 }
6087         }
6088
6089         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6090         if (new_secdesc == NULL) {
6091                 result = WERR_NOMEM;
6092                 goto done;
6093         }
6094
6095         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6096                 result = WERR_OK;
6097                 goto done;
6098         }
6099
6100         result = winreg_set_printer_secdesc(tmp_ctx, b,
6101                                             printer,
6102                                             new_secdesc);
6103
6104 done:
6105         talloc_free(tmp_ctx);
6106         return result;
6107 }
6108
6109 /********************************************************************
6110  Canonicalize printer info from a client
6111  ********************************************************************/
6112
6113 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6114                              struct spoolss_SetPrinterInfo2 *info2,
6115                              int snum)
6116 {
6117         fstring printername;
6118         const char *p;
6119
6120         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6121                 "portname=%s drivername=%s comment=%s location=%s\n",
6122                 info2->servername, info2->printername, info2->sharename,
6123                 info2->portname, info2->drivername, info2->comment,
6124                 info2->location));
6125
6126         /* we force some elements to "correct" values */
6127         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6128         if (info2->servername == NULL) {
6129                 return false;
6130         }
6131         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6132         if (info2->sharename == NULL) {
6133                 return false;
6134         }
6135
6136         /* check to see if we allow printername != sharename */
6137         if (lp_force_printername(snum)) {
6138                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6139                                         lp_netbios_name(), info2->sharename);
6140         } else {
6141                 /* make sure printername is in \\server\printername format */
6142                 fstrcpy(printername, info2->printername);
6143                 p = printername;
6144                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6145                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6146                                 p++;
6147                 }
6148
6149                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6150                                         lp_netbios_name(), p);
6151         }
6152         if (info2->printername == NULL) {
6153                 return false;
6154         }
6155
6156         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6157         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6158
6159         return true;
6160 }
6161
6162 /****************************************************************************
6163 ****************************************************************************/
6164
6165 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6166 {
6167         char *cmd = lp_addport_cmd();
6168         char *command = NULL;
6169         int ret;
6170         bool is_print_op = false;
6171
6172         if ( !*cmd ) {
6173                 return WERR_ACCESS_DENIED;
6174         }
6175
6176         command = talloc_asprintf(ctx,
6177                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6178         if (!command) {
6179                 return WERR_NOMEM;
6180         }
6181
6182         if ( token )
6183                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6184
6185         DEBUG(10,("Running [%s]\n", command));
6186
6187         /********* BEGIN SePrintOperatorPrivilege **********/
6188
6189         if ( is_print_op )
6190                 become_root();
6191
6192         ret = smbrun(command, NULL);
6193
6194         if ( is_print_op )
6195                 unbecome_root();
6196
6197         /********* END SePrintOperatorPrivilege **********/
6198
6199         DEBUGADD(10,("returned [%d]\n", ret));
6200
6201         TALLOC_FREE(command);
6202
6203         if ( ret != 0 ) {
6204                 return WERR_ACCESS_DENIED;
6205         }
6206
6207         return WERR_OK;
6208 }
6209
6210 /****************************************************************************
6211 ****************************************************************************/
6212
6213 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6214                              struct spoolss_SetPrinterInfo2 *info2,
6215                              const char *remote_machine,
6216                              struct messaging_context *msg_ctx)
6217 {
6218         char *cmd = lp_addprinter_cmd();
6219         char **qlines;
6220         char *command = NULL;
6221         int numlines;
6222         int ret;
6223         int fd;
6224         bool is_print_op = false;
6225
6226         if (!remote_machine) {
6227                 return false;
6228         }
6229
6230         command = talloc_asprintf(ctx,
6231                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6232                         cmd, info2->printername, info2->sharename,
6233                         info2->portname, info2->drivername,
6234                         info2->location, info2->comment, remote_machine);
6235         if (!command) {
6236                 return false;
6237         }
6238
6239         if ( token )
6240                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6241
6242         DEBUG(10,("Running [%s]\n", command));
6243
6244         /********* BEGIN SePrintOperatorPrivilege **********/
6245
6246         if ( is_print_op )
6247                 become_root();
6248
6249         if ( (ret = smbrun(command, &fd)) == 0 ) {
6250                 /* Tell everyone we updated smb.conf. */
6251                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6252         }
6253
6254         if ( is_print_op )
6255                 unbecome_root();
6256
6257         /********* END SePrintOperatorPrivilege **********/
6258
6259         DEBUGADD(10,("returned [%d]\n", ret));
6260
6261         TALLOC_FREE(command);
6262
6263         if ( ret != 0 ) {
6264                 if (fd != -1)
6265                         close(fd);
6266                 return false;
6267         }
6268
6269         /* reload our services immediately */
6270         become_root();
6271         reload_services(msg_ctx, -1, false);
6272         unbecome_root();
6273
6274         numlines = 0;
6275         /* Get lines and convert them back to dos-codepage */
6276         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6277         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6278         close(fd);
6279
6280         /* Set the portname to what the script says the portname should be. */
6281         /* but don't require anything to be return from the script exit a good error code */
6282
6283         if (numlines) {
6284                 /* Set the portname to what the script says the portname should be. */
6285                 info2->portname = talloc_strdup(ctx, qlines[0]);
6286                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6287         }
6288
6289         TALLOC_FREE(qlines);
6290         return true;
6291 }
6292
6293 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6294                                const struct auth_session_info *session_info,
6295                                struct messaging_context *msg_ctx,
6296                                int snum,
6297                                struct spoolss_SetPrinterInfo2 *printer,
6298                                struct spoolss_PrinterInfo2 *old_printer)
6299 {
6300         bool force_update = (old_printer == NULL);
6301         const char *dnsdomname;
6302         const char *longname;
6303         const char *uncname;
6304         const char *spooling;
6305         DATA_BLOB buffer;
6306         WERROR result = WERR_OK;
6307         struct dcerpc_binding_handle *b;
6308         TALLOC_CTX *tmp_ctx;
6309
6310         tmp_ctx = talloc_new(mem_ctx);
6311         if (!tmp_ctx) {
6312                 return WERR_NOMEM;
6313         }
6314
6315         result = winreg_printer_binding_handle(tmp_ctx,
6316                                                session_info,
6317                                                msg_ctx,
6318                                                &b);
6319         if (!W_ERROR_IS_OK(result)) {
6320                 goto done;
6321         }
6322
6323         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6324                 push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6325                 winreg_set_printer_dataex(tmp_ctx, b,
6326                                           printer->sharename,
6327                                           SPOOL_DSSPOOLER_KEY,
6328                                           SPOOL_REG_DRIVERNAME,
6329                                           REG_SZ,
6330                                           buffer.data,
6331                                           buffer.length);
6332
6333                 if (!force_update) {
6334                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6335                                 printer->drivername));
6336
6337                         notify_printer_driver(server_event_context(), msg_ctx,
6338                                               snum, printer->drivername ?
6339                                               printer->drivername : "");
6340                 }
6341         }
6342
6343         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6344                 push_reg_sz(tmp_ctx, &buffer, printer->comment);
6345                 winreg_set_printer_dataex(tmp_ctx, b,
6346                                           printer->sharename,
6347                                           SPOOL_DSSPOOLER_KEY,
6348                                           SPOOL_REG_DESCRIPTION,
6349                                           REG_SZ,
6350                                           buffer.data,
6351                                           buffer.length);
6352
6353                 if (!force_update) {
6354                         notify_printer_comment(server_event_context(), msg_ctx,
6355                                                snum, printer->comment ?
6356                                                printer->comment : "");
6357                 }
6358         }
6359
6360         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6361                 push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6362                 winreg_set_printer_dataex(tmp_ctx, b,
6363                                           printer->sharename,
6364                                           SPOOL_DSSPOOLER_KEY,
6365                                           SPOOL_REG_PRINTSHARENAME,
6366                                           REG_SZ,
6367                                           buffer.data,
6368                                           buffer.length);
6369
6370                 if (!force_update) {
6371                         notify_printer_sharename(server_event_context(),
6372                                                  msg_ctx,
6373                                                  snum, printer->sharename ?
6374                                                  printer->sharename : "");
6375                 }
6376         }
6377
6378         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6379                 const char *p;
6380
6381                 p = strrchr(printer->printername, '\\' );
6382                 if (p != NULL) {
6383                         p++;
6384                 } else {
6385                         p = printer->printername;
6386                 }
6387
6388                 push_reg_sz(tmp_ctx, &buffer, p);
6389                 winreg_set_printer_dataex(tmp_ctx, b,
6390                                           printer->sharename,
6391                                           SPOOL_DSSPOOLER_KEY,
6392                                           SPOOL_REG_PRINTERNAME,
6393                                           REG_SZ,
6394                                           buffer.data,
6395                                           buffer.length);
6396
6397                 if (!force_update) {
6398                         notify_printer_printername(server_event_context(),
6399                                                    msg_ctx, snum, p ? p : "");
6400                 }
6401         }
6402
6403         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6404                 push_reg_sz(tmp_ctx, &buffer, printer->portname);
6405                 winreg_set_printer_dataex(tmp_ctx, b,
6406                                           printer->sharename,
6407                                           SPOOL_DSSPOOLER_KEY,
6408                                           SPOOL_REG_PORTNAME,
6409                                           REG_SZ,
6410                                           buffer.data,
6411                                           buffer.length);
6412
6413                 if (!force_update) {
6414                         notify_printer_port(server_event_context(),
6415                                             msg_ctx, snum, printer->portname ?
6416                                             printer->portname : "");
6417                 }
6418         }
6419
6420         if (force_update || !strequal(printer->location, old_printer->location)) {
6421                 push_reg_sz(tmp_ctx, &buffer, printer->location);
6422                 winreg_set_printer_dataex(tmp_ctx, b,
6423                                           printer->sharename,
6424                                           SPOOL_DSSPOOLER_KEY,
6425                                           SPOOL_REG_LOCATION,
6426                                           REG_SZ,
6427                                           buffer.data,
6428                                           buffer.length);
6429
6430                 if (!force_update) {
6431                         notify_printer_location(server_event_context(),
6432                                                 msg_ctx, snum,
6433                                                 printer->location ?
6434                                                 printer->location : "");
6435                 }
6436         }
6437
6438         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6439                 push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6440                 winreg_set_printer_dataex(tmp_ctx, b,
6441                                           printer->sharename,
6442                                           SPOOL_DSSPOOLER_KEY,
6443                                           SPOOL_REG_PRINTSEPARATORFILE,
6444                                           REG_SZ,
6445                                           buffer.data,
6446                                           buffer.length);
6447
6448                 if (!force_update) {
6449                         notify_printer_sepfile(server_event_context(),
6450                                                msg_ctx, snum,
6451                                                printer->sepfile ?
6452                                                printer->sepfile : "");
6453                 }
6454         }
6455
6456         if (force_update || printer->starttime != old_printer->starttime) {
6457                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6458                 SIVAL(buffer.data, 0, printer->starttime);
6459                 winreg_set_printer_dataex(tmp_ctx, b,
6460                                           printer->sharename,
6461                                           SPOOL_DSSPOOLER_KEY,
6462                                           SPOOL_REG_PRINTSTARTTIME,
6463                                           REG_DWORD,
6464                                           buffer.data,
6465                                           buffer.length);
6466         }
6467
6468         if (force_update || printer->untiltime != old_printer->untiltime) {
6469                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6470                 SIVAL(buffer.data, 0, printer->untiltime);
6471                 winreg_set_printer_dataex(tmp_ctx, b,
6472                                           printer->sharename,
6473                                           SPOOL_DSSPOOLER_KEY,
6474                                           SPOOL_REG_PRINTENDTIME,
6475                                           REG_DWORD,
6476                                           buffer.data,
6477                                           buffer.length);
6478         }
6479
6480         if (force_update || printer->priority != old_printer->priority) {
6481                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6482                 SIVAL(buffer.data, 0, printer->priority);
6483                 winreg_set_printer_dataex(tmp_ctx, b,
6484                                           printer->sharename,
6485                                           SPOOL_DSSPOOLER_KEY,
6486                                           SPOOL_REG_PRIORITY,
6487                                           REG_DWORD,
6488                                           buffer.data,
6489                                           buffer.length);
6490         }
6491
6492         if (force_update || printer->attributes != old_printer->attributes) {
6493                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6494                 SIVAL(buffer.data, 0, (printer->attributes &
6495                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6496                 winreg_set_printer_dataex(tmp_ctx, b,
6497                                           printer->sharename,
6498                                           SPOOL_DSSPOOLER_KEY,
6499                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6500                                           REG_DWORD,
6501                                           buffer.data,
6502                                           buffer.length);
6503
6504                 switch (printer->attributes & 0x3) {
6505                         case 0:
6506                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6507                                 break;
6508                         case 1:
6509                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6510                                 break;
6511                         case 2:
6512                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6513                                 break;
6514                         default:
6515                                 spooling = "unknown";
6516                 }
6517                 push_reg_sz(tmp_ctx, &buffer, spooling);
6518                 winreg_set_printer_dataex(tmp_ctx, b,
6519                                           printer->sharename,
6520                                           SPOOL_DSSPOOLER_KEY,
6521                                           SPOOL_REG_PRINTSPOOLING,
6522                                           REG_SZ,
6523                                           buffer.data,
6524                                           buffer.length);
6525         }
6526
6527         push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6528         winreg_set_printer_dataex(tmp_ctx, b,
6529                                   printer->sharename,
6530                                   SPOOL_DSSPOOLER_KEY,
6531                                   SPOOL_REG_SHORTSERVERNAME,
6532                                   REG_SZ,
6533                                   buffer.data,
6534                                   buffer.length);
6535
6536         dnsdomname = get_mydnsfullname();
6537         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6538                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6539         } else {
6540                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6541         }
6542         if (longname == NULL) {
6543                 result = WERR_NOMEM;
6544                 goto done;
6545         }
6546
6547         push_reg_sz(tmp_ctx, &buffer, longname);
6548         winreg_set_printer_dataex(tmp_ctx, b,
6549                                   printer->sharename,
6550                                   SPOOL_DSSPOOLER_KEY,
6551                                   SPOOL_REG_SERVERNAME,
6552                                   REG_SZ,
6553                                   buffer.data,
6554                                   buffer.length);
6555
6556         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6557                                   lp_netbios_name(), printer->sharename);
6558         push_reg_sz(tmp_ctx, &buffer, uncname);
6559         winreg_set_printer_dataex(tmp_ctx, b,
6560                                   printer->sharename,
6561                                   SPOOL_DSSPOOLER_KEY,
6562                                   SPOOL_REG_UNCNAME,
6563                                   REG_SZ,
6564                                   buffer.data,
6565                                   buffer.length);
6566
6567 done:
6568         talloc_free(tmp_ctx);
6569         return result;
6570 }
6571
6572 /********************************************************************
6573  * Called by spoolss_api_setprinter
6574  * when updating a printer description.
6575  ********************************************************************/
6576
6577 static WERROR update_printer(struct pipes_struct *p,
6578                              struct policy_handle *handle,
6579                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6580                              struct spoolss_DeviceMode *devmode)
6581 {
6582         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6583         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6584         struct spoolss_PrinterInfo2 *old_printer;
6585         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6586         int snum;
6587         WERROR result = WERR_OK;
6588         TALLOC_CTX *tmp_ctx;
6589         struct dcerpc_binding_handle *b;
6590
6591         DEBUG(8,("update_printer\n"));
6592
6593         tmp_ctx = talloc_new(p->mem_ctx);
6594         if (tmp_ctx == NULL) {
6595                 return WERR_NOMEM;
6596         }
6597
6598         if (!Printer) {
6599                 result = WERR_BADFID;
6600                 goto done;
6601         }
6602
6603         if (!get_printer_snum(p, handle, &snum, NULL)) {
6604                 result = WERR_BADFID;
6605                 goto done;
6606         }
6607
6608         result = winreg_printer_binding_handle(tmp_ctx,
6609                                                get_session_info_system(),
6610                                                p->msg_ctx,
6611                                                &b);
6612         if (!W_ERROR_IS_OK(result)) {
6613                 goto done;
6614         }
6615
6616         result = winreg_get_printer(tmp_ctx, b,
6617                                     lp_const_servicename(snum),
6618                                     &old_printer);
6619         if (!W_ERROR_IS_OK(result)) {
6620                 result = WERR_BADFID;
6621                 goto done;
6622         }
6623
6624         /* Do sanity check on the requested changes for Samba */
6625         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6626                 result = WERR_INVALID_PARAM;
6627                 goto done;
6628         }
6629
6630         /* FIXME!!! If the driver has changed we really should verify that
6631            it is installed before doing much else   --jerry */
6632
6633         /* Check calling user has permission to update printer description */
6634         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6635                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6636                 result = WERR_ACCESS_DENIED;
6637                 goto done;
6638         }
6639
6640         /* Call addprinter hook */
6641         /* Check changes to see if this is really needed */
6642
6643         if (*lp_addprinter_cmd() &&
6644                         (!strequal(printer->drivername, old_printer->drivername) ||
6645                          !strequal(printer->comment, old_printer->comment) ||
6646                          !strequal(printer->portname, old_printer->portname) ||
6647                          !strequal(printer->location, old_printer->location)) )
6648         {
6649                 char *raddr;
6650
6651                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6652                                                          p->mem_ctx);
6653                 if (raddr == NULL) {
6654                         return WERR_NOMEM;
6655                 }
6656
6657                 /* add_printer_hook() will call reload_services() */
6658                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6659                                       printer, raddr,
6660                                       p->msg_ctx)) {
6661                         result = WERR_ACCESS_DENIED;
6662                         goto done;
6663                 }
6664         }
6665
6666         update_dsspooler(tmp_ctx,
6667                          get_session_info_system(),
6668                          p->msg_ctx,
6669                          snum,
6670                          printer,
6671                          old_printer);
6672
6673         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6674
6675         if (devmode == NULL) {
6676                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6677         }
6678         result = winreg_update_printer(tmp_ctx, b,
6679                                        printer->sharename,
6680                                        printer_mask,
6681                                        printer,
6682                                        devmode,
6683                                        NULL);
6684
6685 done:
6686         talloc_free(tmp_ctx);
6687
6688         return result;
6689 }
6690
6691 /****************************************************************************
6692 ****************************************************************************/
6693 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6694                                            struct policy_handle *handle,
6695                                            struct spoolss_SetPrinterInfo7 *info7)
6696 {
6697 #ifdef HAVE_ADS
6698         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6699         WERROR result;
6700         int snum;
6701         struct printer_handle *Printer;
6702
6703         if ( lp_security() != SEC_ADS ) {
6704                 return WERR_UNKNOWN_LEVEL;
6705         }
6706
6707         Printer = find_printer_index_by_hnd(p, handle);
6708
6709         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6710
6711         if (!Printer)
6712                 return WERR_BADFID;
6713
6714         if (!get_printer_snum(p, handle, &snum, NULL))
6715                 return WERR_BADFID;
6716
6717         result = winreg_get_printer_internal(p->mem_ctx,
6718                                     get_session_info_system(),
6719                                     p->msg_ctx,
6720                                     lp_servicename(snum),
6721                                     &pinfo2);
6722         if (!W_ERROR_IS_OK(result)) {
6723                 return WERR_BADFID;
6724         }
6725
6726         nt_printer_publish(pinfo2,
6727                            get_session_info_system(),
6728                            p->msg_ctx,
6729                            pinfo2,
6730                            info7->action);
6731
6732         TALLOC_FREE(pinfo2);
6733         return WERR_OK;
6734 #else
6735         return WERR_UNKNOWN_LEVEL;
6736 #endif
6737 }
6738
6739 /********************************************************************
6740  ********************************************************************/
6741
6742 static WERROR update_printer_devmode(struct pipes_struct *p,
6743                                      struct policy_handle *handle,
6744                                      struct spoolss_DeviceMode *devmode)
6745 {
6746         int snum;
6747         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6748         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6749
6750         DEBUG(8,("update_printer_devmode\n"));
6751
6752         if (!Printer) {
6753                 return WERR_BADFID;
6754         }
6755
6756         if (!get_printer_snum(p, handle, &snum, NULL)) {
6757                 return WERR_BADFID;
6758         }
6759
6760         /* Check calling user has permission to update printer description */
6761         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6762                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6763                 return WERR_ACCESS_DENIED;
6764         }
6765
6766         return winreg_update_printer_internal(p->mem_ctx,
6767                                      get_session_info_system(),
6768                                      p->msg_ctx,
6769                                      lp_const_servicename(snum),
6770                                      info2_mask,
6771                                      NULL,
6772                                      devmode,
6773                                      NULL);
6774 }
6775
6776
6777 /****************************************************************
6778  _spoolss_SetPrinter
6779 ****************************************************************/
6780
6781 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6782                            struct spoolss_SetPrinter *r)
6783 {
6784         WERROR result;
6785
6786         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6787
6788         if (!Printer) {
6789                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6790                         OUR_HANDLE(r->in.handle)));
6791                 return WERR_BADFID;
6792         }
6793
6794         /* check the level */
6795         switch (r->in.info_ctr->level) {
6796                 case 0:
6797                         return control_printer(r->in.handle, r->in.command, p);
6798                 case 2:
6799                         result = update_printer(p, r->in.handle,
6800                                                 r->in.info_ctr,
6801                                                 r->in.devmode_ctr->devmode);
6802                         if (!W_ERROR_IS_OK(result))
6803                                 return result;
6804                         if (r->in.secdesc_ctr->sd)
6805                                 result = update_printer_sec(r->in.handle, p,
6806                                                             r->in.secdesc_ctr);
6807                         return result;
6808                 case 3:
6809                         return update_printer_sec(r->in.handle, p,
6810                                                   r->in.secdesc_ctr);
6811                 case 7:
6812                         return publish_or_unpublish_printer(p, r->in.handle,
6813                                                             r->in.info_ctr->info.info7);
6814                 case 8:
6815                         return update_printer_devmode(p, r->in.handle,
6816                                                       r->in.devmode_ctr->devmode);
6817                 default:
6818                         return WERR_UNKNOWN_LEVEL;
6819         }
6820 }
6821
6822 /****************************************************************
6823  _spoolss_FindClosePrinterNotify
6824 ****************************************************************/
6825
6826 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6827                                        struct spoolss_FindClosePrinterNotify *r)
6828 {
6829         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6830
6831         if (!Printer) {
6832                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6833                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6834                 return WERR_BADFID;
6835         }
6836
6837         if (Printer->notify.cli_chan != NULL &&
6838             Printer->notify.cli_chan->active_connections > 0) {
6839                 int snum = -1;
6840
6841                 if (Printer->printer_type == SPLHND_PRINTER) {
6842                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6843                                 return WERR_BADFID;
6844                         }
6845                 }
6846
6847                 srv_spoolss_replycloseprinter(snum, Printer);
6848         }
6849
6850         Printer->notify.flags=0;
6851         Printer->notify.options=0;
6852         Printer->notify.localmachine[0]='\0';
6853         Printer->notify.printerlocal=0;
6854         TALLOC_FREE(Printer->notify.option);
6855
6856         return WERR_OK;
6857 }
6858
6859 /****************************************************************
6860  _spoolss_AddJob
6861 ****************************************************************/
6862
6863 WERROR _spoolss_AddJob(struct pipes_struct *p,
6864                        struct spoolss_AddJob *r)
6865 {
6866         if (!r->in.buffer && (r->in.offered != 0)) {
6867                 return WERR_INVALID_PARAM;
6868         }
6869
6870         /* this is what a NT server returns for AddJob. AddJob must fail on
6871          * non-local printers */
6872
6873         if (r->in.level != 1) {
6874                 return WERR_UNKNOWN_LEVEL;
6875         }
6876
6877         return WERR_INVALID_PARAM;
6878 }
6879
6880 /****************************************************************************
6881 fill_job_info1
6882 ****************************************************************************/
6883
6884 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6885                              struct spoolss_JobInfo1 *r,
6886                              const print_queue_struct *queue,
6887                              int position, int snum,
6888                              struct spoolss_PrinterInfo2 *pinfo2)
6889 {
6890         struct tm *t;
6891
6892         t = gmtime(&queue->time);
6893
6894         r->job_id               = queue->job;
6895
6896         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6897         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6898         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6899         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6900         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6901         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6902         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6903         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6904         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6905         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6906         r->text_status          = talloc_strdup(mem_ctx, "");
6907         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6908
6909         r->status               = nt_printj_status(queue->status);
6910         r->priority             = queue->priority;
6911         r->position             = position;
6912         r->total_pages          = queue->page_count;
6913         r->pages_printed        = 0; /* ??? */
6914
6915         init_systemtime(&r->submitted, t);
6916
6917         return WERR_OK;
6918 }
6919
6920 /****************************************************************************
6921 fill_job_info2
6922 ****************************************************************************/
6923
6924 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6925                              struct spoolss_JobInfo2 *r,
6926                              const print_queue_struct *queue,
6927                              int position, int snum,
6928                              struct spoolss_PrinterInfo2 *pinfo2,
6929                              struct spoolss_DeviceMode *devmode)
6930 {
6931         struct tm *t;
6932
6933         t = gmtime(&queue->time);
6934
6935         r->job_id               = queue->job;
6936
6937         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6938         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6939         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6940         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6941         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6942         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6943         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6944         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6945         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6946         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6947         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6948         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6949         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6950         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6951         r->parameters           = talloc_strdup(mem_ctx, "");
6952         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6953         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6954         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6955
6956         r->devmode              = devmode;
6957
6958         r->text_status          = talloc_strdup(mem_ctx, "");
6959         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6960
6961         r->secdesc              = NULL;
6962
6963         r->status               = nt_printj_status(queue->status);
6964         r->priority             = queue->priority;
6965         r->position             = position;
6966         r->start_time           = 0;
6967         r->until_time           = 0;
6968         r->total_pages          = queue->page_count;
6969         r->size                 = queue->size;
6970         init_systemtime(&r->submitted, t);
6971         r->time                 = 0;
6972         r->pages_printed        = 0; /* ??? */
6973
6974         return WERR_OK;
6975 }
6976
6977 /****************************************************************************
6978 fill_job_info3
6979 ****************************************************************************/
6980
6981 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6982                              struct spoolss_JobInfo3 *r,
6983                              const print_queue_struct *queue,
6984                              const print_queue_struct *next_queue,
6985                              int position, int snum,
6986                              struct spoolss_PrinterInfo2 *pinfo2)
6987 {
6988         r->job_id               = queue->job;
6989         r->next_job_id          = 0;
6990         if (next_queue) {
6991                 r->next_job_id  = next_queue->job;
6992         }
6993         r->reserved             = 0;
6994
6995         return WERR_OK;
6996 }
6997
6998 /****************************************************************************
6999  Enumjobs at level 1.
7000 ****************************************************************************/
7001
7002 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7003                               const print_queue_struct *queue,
7004                               uint32_t num_queues, int snum,
7005                               struct spoolss_PrinterInfo2 *pinfo2,
7006                               union spoolss_JobInfo **info_p,
7007                               uint32_t *count)
7008 {
7009         union spoolss_JobInfo *info;
7010         int i;
7011         WERROR result = WERR_OK;
7012
7013         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7014         W_ERROR_HAVE_NO_MEMORY(info);
7015
7016         *count = num_queues;
7017
7018         for (i=0; i<*count; i++) {
7019                 result = fill_job_info1(info,
7020                                         &info[i].info1,
7021                                         &queue[i],
7022                                         i,
7023                                         snum,
7024                                         pinfo2);
7025                 if (!W_ERROR_IS_OK(result)) {
7026                         goto out;
7027                 }
7028         }
7029
7030  out:
7031         if (!W_ERROR_IS_OK(result)) {
7032                 TALLOC_FREE(info);
7033                 *count = 0;
7034                 return result;
7035         }
7036
7037         *info_p = info;
7038
7039         return WERR_OK;
7040 }
7041
7042 /****************************************************************************
7043  Enumjobs at level 2.
7044 ****************************************************************************/
7045
7046 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7047                               const print_queue_struct *queue,
7048                               uint32_t num_queues, int snum,
7049                               struct spoolss_PrinterInfo2 *pinfo2,
7050                               union spoolss_JobInfo **info_p,
7051                               uint32_t *count)
7052 {
7053         union spoolss_JobInfo *info;
7054         int i;
7055         WERROR result = WERR_OK;
7056
7057         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7058         W_ERROR_HAVE_NO_MEMORY(info);
7059
7060         *count = num_queues;
7061
7062         for (i=0; i<*count; i++) {
7063                 struct spoolss_DeviceMode *devmode;
7064
7065                 result = spoolss_create_default_devmode(info,
7066                                                         pinfo2->printername,
7067                                                         &devmode);
7068                 if (!W_ERROR_IS_OK(result)) {
7069                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7070                         goto out;
7071                 }
7072
7073                 result = fill_job_info2(info,
7074                                         &info[i].info2,
7075                                         &queue[i],
7076                                         i,
7077                                         snum,
7078                                         pinfo2,
7079                                         devmode);
7080                 if (!W_ERROR_IS_OK(result)) {
7081                         goto out;
7082                 }
7083         }
7084
7085  out:
7086         if (!W_ERROR_IS_OK(result)) {
7087                 TALLOC_FREE(info);
7088                 *count = 0;
7089                 return result;
7090         }
7091
7092         *info_p = info;
7093
7094         return WERR_OK;
7095 }
7096
7097 /****************************************************************************
7098  Enumjobs at level 3.
7099 ****************************************************************************/
7100
7101 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7102                               const print_queue_struct *queue,
7103                               uint32_t num_queues, int snum,
7104                               struct spoolss_PrinterInfo2 *pinfo2,
7105                               union spoolss_JobInfo **info_p,
7106                               uint32_t *count)
7107 {
7108         union spoolss_JobInfo *info;
7109         int i;
7110         WERROR result = WERR_OK;
7111
7112         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7113         W_ERROR_HAVE_NO_MEMORY(info);
7114
7115         *count = num_queues;
7116
7117         for (i=0; i<*count; i++) {
7118                 const print_queue_struct *next_queue = NULL;
7119
7120                 if (i+1 < *count) {
7121                         next_queue = &queue[i+1];
7122                 }
7123
7124                 result = fill_job_info3(info,
7125                                         &info[i].info3,
7126                                         &queue[i],
7127                                         next_queue,
7128                                         i,
7129                                         snum,
7130                                         pinfo2);
7131                 if (!W_ERROR_IS_OK(result)) {
7132                         goto out;
7133                 }
7134         }
7135
7136  out:
7137         if (!W_ERROR_IS_OK(result)) {
7138                 TALLOC_FREE(info);
7139                 *count = 0;
7140                 return result;
7141         }
7142
7143         *info_p = info;
7144
7145         return WERR_OK;
7146 }
7147
7148 /****************************************************************
7149  _spoolss_EnumJobs
7150 ****************************************************************/
7151
7152 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7153                          struct spoolss_EnumJobs *r)
7154 {
7155         WERROR result;
7156         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7157         int snum;
7158         print_status_struct prt_status;
7159         print_queue_struct *queue = NULL;
7160         uint32_t count;
7161
7162         /* that's an [in out] buffer */
7163
7164         if (!r->in.buffer && (r->in.offered != 0)) {
7165                 return WERR_INVALID_PARAM;
7166         }
7167
7168         DEBUG(4,("_spoolss_EnumJobs\n"));
7169
7170         *r->out.needed = 0;
7171         *r->out.count = 0;
7172         *r->out.info = NULL;
7173
7174         /* lookup the printer snum and tdb entry */
7175
7176         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7177                 return WERR_BADFID;
7178         }
7179
7180         result = winreg_get_printer_internal(p->mem_ctx,
7181                                     get_session_info_system(),
7182                                     p->msg_ctx,
7183                                     lp_const_servicename(snum),
7184                                     &pinfo2);
7185         if (!W_ERROR_IS_OK(result)) {
7186                 return result;
7187         }
7188
7189         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7190         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7191                 count, prt_status.status, prt_status.message));
7192
7193         if (count == 0) {
7194                 SAFE_FREE(queue);
7195                 TALLOC_FREE(pinfo2);
7196                 return WERR_OK;
7197         }
7198
7199         switch (r->in.level) {
7200         case 1:
7201                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7202                                          pinfo2, r->out.info, r->out.count);
7203                 break;
7204         case 2:
7205                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7206                                          pinfo2, r->out.info, r->out.count);
7207                 break;
7208         case 3:
7209                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7210                                          pinfo2, r->out.info, r->out.count);
7211                 break;
7212         default:
7213                 result = WERR_UNKNOWN_LEVEL;
7214                 break;
7215         }
7216
7217         SAFE_FREE(queue);
7218         TALLOC_FREE(pinfo2);
7219
7220         if (!W_ERROR_IS_OK(result)) {
7221                 return result;
7222         }
7223
7224         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7225                                                      spoolss_EnumJobs,
7226                                                      *r->out.info, r->in.level,
7227                                                      *r->out.count);
7228         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7229         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7230
7231         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7232 }
7233
7234 /****************************************************************
7235  _spoolss_ScheduleJob
7236 ****************************************************************/
7237
7238 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7239                             struct spoolss_ScheduleJob *r)
7240 {
7241         return WERR_OK;
7242 }
7243
7244 /****************************************************************
7245 ****************************************************************/
7246
7247 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7248                                struct messaging_context *msg_ctx,
7249                                const char *printer_name,
7250                                uint32_t job_id,
7251                                struct spoolss_SetJobInfo1 *r)
7252 {
7253         char *old_doc_name;
7254
7255         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7256                 return WERR_BADFID;
7257         }
7258
7259         if (strequal(old_doc_name, r->document_name)) {
7260                 return WERR_OK;
7261         }
7262
7263         if (!print_job_set_name(server_event_context(), msg_ctx,
7264                                 printer_name, job_id, r->document_name)) {
7265                 return WERR_BADFID;
7266         }
7267
7268         return WERR_OK;
7269 }
7270
7271 /****************************************************************
7272  _spoolss_SetJob
7273 ****************************************************************/
7274
7275 WERROR _spoolss_SetJob(struct pipes_struct *p,
7276                        struct spoolss_SetJob *r)
7277 {
7278         const struct auth_session_info *session_info = p->session_info;
7279         int snum;
7280         WERROR errcode = WERR_BADFUNC;
7281
7282         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7283                 return WERR_BADFID;
7284         }
7285
7286         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7287                 return WERR_INVALID_PRINTER_NAME;
7288         }
7289
7290         switch (r->in.command) {
7291         case SPOOLSS_JOB_CONTROL_CANCEL:
7292         case SPOOLSS_JOB_CONTROL_DELETE:
7293                 errcode = print_job_delete(session_info, p->msg_ctx,
7294                                            snum, r->in.job_id);
7295                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7296                         errcode = WERR_OK;
7297                 }
7298                 break;
7299         case SPOOLSS_JOB_CONTROL_PAUSE:
7300                 if (print_job_pause(session_info, p->msg_ctx,
7301                                     snum, r->in.job_id, &errcode)) {
7302                         errcode = WERR_OK;
7303                 }
7304                 break;
7305         case SPOOLSS_JOB_CONTROL_RESTART:
7306         case SPOOLSS_JOB_CONTROL_RESUME:
7307                 if (print_job_resume(session_info, p->msg_ctx,
7308                                      snum, r->in.job_id, &errcode)) {
7309                         errcode = WERR_OK;
7310                 }
7311                 break;
7312         case 0:
7313                 errcode = WERR_OK;
7314                 break;
7315         default:
7316                 return WERR_UNKNOWN_LEVEL;
7317         }
7318
7319         if (!W_ERROR_IS_OK(errcode)) {
7320                 return errcode;
7321         }
7322
7323         if (r->in.ctr == NULL) {
7324                 return errcode;
7325         }
7326
7327         switch (r->in.ctr->level) {
7328         case 1:
7329                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7330                                            lp_const_servicename(snum),
7331                                            r->in.job_id,
7332                                            r->in.ctr->info.info1);
7333                 break;
7334         case 2:
7335         case 3:
7336         case 4:
7337         default:
7338                 return WERR_UNKNOWN_LEVEL;
7339         }
7340
7341         return errcode;
7342 }
7343
7344 /****************************************************************************
7345  Enumerates all printer drivers by level and architecture.
7346 ****************************************************************************/
7347
7348 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7349                                                        const struct auth_session_info *session_info,
7350                                                        struct messaging_context *msg_ctx,
7351                                                        const char *servername,
7352                                                        const char *architecture,
7353                                                        uint32_t level,
7354                                                        union spoolss_DriverInfo **info_p,
7355                                                        uint32_t *count_p)
7356 {
7357         int i;
7358         uint32_t version;
7359         struct spoolss_DriverInfo8 *driver;
7360         union spoolss_DriverInfo *info = NULL;
7361         uint32_t count = 0;
7362         WERROR result = WERR_OK;
7363         uint32_t num_drivers;
7364         const char **drivers;
7365         struct dcerpc_binding_handle *b;
7366         TALLOC_CTX *tmp_ctx = NULL;
7367
7368         *count_p = 0;
7369         *info_p = NULL;
7370
7371         tmp_ctx = talloc_new(mem_ctx);
7372         if (!tmp_ctx) {
7373                 return WERR_NOMEM;
7374         }
7375
7376         result = winreg_printer_binding_handle(tmp_ctx,
7377                                                session_info,
7378                                                msg_ctx,
7379                                                &b);
7380         if (!W_ERROR_IS_OK(result)) {
7381                 goto out;
7382         }
7383
7384         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7385                 result = winreg_get_driver_list(tmp_ctx, b,
7386                                                 architecture, version,
7387                                                 &num_drivers, &drivers);
7388                 if (!W_ERROR_IS_OK(result)) {
7389                         goto out;
7390                 }
7391                 DEBUG(4, ("we have:[%d] drivers in environment"
7392                           " [%s] and version [%d]\n",
7393                           num_drivers, architecture, version));
7394
7395                 if (num_drivers != 0) {
7396                         info = talloc_realloc(tmp_ctx, info,
7397                                                     union spoolss_DriverInfo,
7398                                                     count + num_drivers);
7399                         if (!info) {
7400                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7401                                         "failed to enlarge driver info buffer!\n"));
7402                                 result = WERR_NOMEM;
7403                                 goto out;
7404                         }
7405                 }
7406
7407                 for (i = 0; i < num_drivers; i++) {
7408                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7409
7410                         result = winreg_get_driver(tmp_ctx, b,
7411                                                    architecture, drivers[i],
7412                                                    version, &driver);
7413                         if (!W_ERROR_IS_OK(result)) {
7414                                 goto out;
7415                         }
7416
7417                         switch (level) {
7418                         case 1:
7419                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7420                                                                    driver, servername);
7421                                 break;
7422                         case 2:
7423                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7424                                                                    driver, servername);
7425                                 break;
7426                         case 3:
7427                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7428                                                                    driver, servername);
7429                                 break;
7430                         case 4:
7431                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7432                                                                    driver, servername);
7433                                 break;
7434                         case 5:
7435                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7436                                                                    driver, servername);
7437                                 break;
7438                         case 6:
7439                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7440                                                                    driver, servername);
7441                                 break;
7442                         case 8:
7443                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7444                                                                    driver, servername);
7445                                 break;
7446                         default:
7447                                 result = WERR_UNKNOWN_LEVEL;
7448                                 break;
7449                         }
7450
7451                         TALLOC_FREE(driver);
7452
7453                         if (!W_ERROR_IS_OK(result)) {
7454                                 goto out;
7455                         }
7456                 }
7457
7458                 count += num_drivers;
7459                 TALLOC_FREE(drivers);
7460         }
7461
7462 out:
7463         if (W_ERROR_IS_OK(result)) {
7464                 *info_p = talloc_move(mem_ctx, &info);
7465                 *count_p = count;
7466         }
7467
7468         talloc_free(tmp_ctx);
7469         return result;
7470 }
7471
7472 /****************************************************************************
7473  Enumerates all printer drivers by level.
7474 ****************************************************************************/
7475
7476 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7477                                        const struct auth_session_info *session_info,
7478                                        struct messaging_context *msg_ctx,
7479                                        const char *servername,
7480                                        const char *architecture,
7481                                        uint32_t level,
7482                                        union spoolss_DriverInfo **info_p,
7483                                        uint32_t *count_p)
7484 {
7485         uint32_t a,i;
7486         WERROR result = WERR_OK;
7487
7488         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7489
7490                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7491
7492                         union spoolss_DriverInfo *info = NULL;
7493                         uint32_t count = 0;
7494
7495                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7496                                                                           session_info,
7497                                                                           msg_ctx,
7498                                                                           servername,
7499                                                                           archi_table[a].long_archi,
7500                                                                           level,
7501                                                                           &info,
7502                                                                           &count);
7503                         if (!W_ERROR_IS_OK(result)) {
7504                                 continue;
7505                         }
7506
7507                         for (i=0; i < count; i++) {
7508                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7509                                              info[i], info_p, count_p);
7510                         }
7511                 }
7512
7513                 return result;
7514         }
7515
7516         return enumprinterdrivers_level_by_architecture(mem_ctx,
7517                                                         session_info,
7518                                                         msg_ctx,
7519                                                         servername,
7520                                                         architecture,
7521                                                         level,
7522                                                         info_p,
7523                                                         count_p);
7524 }
7525
7526 /****************************************************************
7527  _spoolss_EnumPrinterDrivers
7528 ****************************************************************/
7529
7530 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7531                                    struct spoolss_EnumPrinterDrivers *r)
7532 {
7533         const char *cservername;
7534         WERROR result;
7535
7536         /* that's an [in out] buffer */
7537
7538         if (!r->in.buffer && (r->in.offered != 0)) {
7539                 return WERR_INVALID_PARAM;
7540         }
7541
7542         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7543
7544         *r->out.needed = 0;
7545         *r->out.count = 0;
7546         *r->out.info = NULL;
7547
7548         cservername = canon_servername(r->in.server);
7549
7550         if (!is_myname_or_ipaddr(cservername)) {
7551                 return WERR_UNKNOWN_PRINTER_DRIVER;
7552         }
7553
7554         result = enumprinterdrivers_level(p->mem_ctx,
7555                                           get_session_info_system(),
7556                                           p->msg_ctx,
7557                                           cservername,
7558                                           r->in.environment,
7559                                           r->in.level,
7560                                           r->out.info,
7561                                           r->out.count);
7562         if (!W_ERROR_IS_OK(result)) {
7563                 return result;
7564         }
7565
7566         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7567                                                      spoolss_EnumPrinterDrivers,
7568                                                      *r->out.info, r->in.level,
7569                                                      *r->out.count);
7570         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7571         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7572
7573         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7574 }
7575
7576 /****************************************************************
7577  _spoolss_EnumForms
7578 ****************************************************************/
7579
7580 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7581                           struct spoolss_EnumForms *r)
7582 {
7583         WERROR result;
7584
7585         *r->out.count = 0;
7586         *r->out.needed = 0;
7587         *r->out.info = NULL;
7588
7589         /* that's an [in out] buffer */
7590
7591         if (!r->in.buffer && (r->in.offered != 0) ) {
7592                 return WERR_INVALID_PARAM;
7593         }
7594
7595         DEBUG(4,("_spoolss_EnumForms\n"));
7596         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7597         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7598
7599         switch (r->in.level) {
7600         case 1:
7601                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7602                                                    get_session_info_system(),
7603                                                    p->msg_ctx,
7604                                                    r->out.count,
7605                                                    r->out.info);
7606                 break;
7607         default:
7608                 result = WERR_UNKNOWN_LEVEL;
7609                 break;
7610         }
7611
7612         if (!W_ERROR_IS_OK(result)) {
7613                 return result;
7614         }
7615
7616         if (*r->out.count == 0) {
7617                 return WERR_NO_MORE_ITEMS;
7618         }
7619
7620         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7621                                                      spoolss_EnumForms,
7622                                                      *r->out.info, r->in.level,
7623                                                      *r->out.count);
7624         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7625         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7626
7627         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7628 }
7629
7630 /****************************************************************
7631  _spoolss_GetForm
7632 ****************************************************************/
7633
7634 WERROR _spoolss_GetForm(struct pipes_struct *p,
7635                         struct spoolss_GetForm *r)
7636 {
7637         WERROR result;
7638
7639         /* that's an [in out] buffer */
7640
7641         if (!r->in.buffer && (r->in.offered != 0)) {
7642                 return WERR_INVALID_PARAM;
7643         }
7644
7645         DEBUG(4,("_spoolss_GetForm\n"));
7646         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7647         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7648
7649         switch (r->in.level) {
7650         case 1:
7651                 result = winreg_printer_getform1_internal(p->mem_ctx,
7652                                                  get_session_info_system(),
7653                                                  p->msg_ctx,
7654                                                  r->in.form_name,
7655                                                  &r->out.info->info1);
7656                 break;
7657         default:
7658                 result = WERR_UNKNOWN_LEVEL;
7659                 break;
7660         }
7661
7662         if (!W_ERROR_IS_OK(result)) {
7663                 TALLOC_FREE(r->out.info);
7664                 return result;
7665         }
7666
7667         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7668                                                r->out.info, r->in.level);
7669         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7670
7671         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7672 }
7673
7674 /****************************************************************************
7675 ****************************************************************************/
7676
7677 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7678                           struct spoolss_PortInfo1 *r,
7679                           const char *name)
7680 {
7681         r->port_name = talloc_strdup(mem_ctx, name);
7682         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7683
7684         return WERR_OK;
7685 }
7686
7687 /****************************************************************************
7688  TODO: This probably needs distinguish between TCP/IP and Local ports
7689  somehow.
7690 ****************************************************************************/
7691
7692 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7693                           struct spoolss_PortInfo2 *r,
7694                           const char *name)
7695 {
7696         r->port_name = talloc_strdup(mem_ctx, name);
7697         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7698
7699         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7700         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7701
7702         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7703         W_ERROR_HAVE_NO_MEMORY(r->description);
7704
7705         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7706         r->reserved = 0;
7707
7708         return WERR_OK;
7709 }
7710
7711
7712 /****************************************************************************
7713  wrapper around the enumer ports command
7714 ****************************************************************************/
7715
7716 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7717 {
7718         char *cmd = lp_enumports_cmd();
7719         char **qlines = NULL;
7720         char *command = NULL;
7721         int numlines;
7722         int ret;
7723         int fd;
7724
7725         *count = 0;
7726         *lines = NULL;
7727
7728         /* if no hook then just fill in the default port */
7729
7730         if ( !*cmd ) {
7731                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7732                         return WERR_NOMEM;
7733                 }
7734                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7735                         TALLOC_FREE(qlines);
7736                         return WERR_NOMEM;
7737                 }
7738                 qlines[1] = NULL;
7739                 numlines = 1;
7740         }
7741         else {
7742                 /* we have a valid enumport command */
7743
7744                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7745                 if (!command) {
7746                         return WERR_NOMEM;
7747                 }
7748
7749                 DEBUG(10,("Running [%s]\n", command));
7750                 ret = smbrun(command, &fd);
7751                 DEBUG(10,("Returned [%d]\n", ret));
7752                 TALLOC_FREE(command);
7753                 if (ret != 0) {
7754                         if (fd != -1) {
7755                                 close(fd);
7756                         }
7757                         return WERR_ACCESS_DENIED;
7758                 }
7759
7760                 numlines = 0;
7761                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7762                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7763                 close(fd);
7764         }
7765
7766         *count = numlines;
7767         *lines = qlines;
7768
7769         return WERR_OK;
7770 }
7771
7772 /****************************************************************************
7773  enumports level 1.
7774 ****************************************************************************/
7775
7776 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7777                                 union spoolss_PortInfo **info_p,
7778                                 uint32_t *count)
7779 {
7780         union spoolss_PortInfo *info = NULL;
7781         int i=0;
7782         WERROR result = WERR_OK;
7783         char **qlines = NULL;
7784         int numlines = 0;
7785
7786         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7787         if (!W_ERROR_IS_OK(result)) {
7788                 goto out;
7789         }
7790
7791         if (numlines) {
7792                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7793                 if (!info) {
7794                         DEBUG(10,("Returning WERR_NOMEM\n"));
7795                         result = WERR_NOMEM;
7796                         goto out;
7797                 }
7798
7799                 for (i=0; i<numlines; i++) {
7800                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7801                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7802                         if (!W_ERROR_IS_OK(result)) {
7803                                 goto out;
7804                         }
7805                 }
7806         }
7807         TALLOC_FREE(qlines);
7808
7809 out:
7810         if (!W_ERROR_IS_OK(result)) {
7811                 TALLOC_FREE(info);
7812                 TALLOC_FREE(qlines);
7813                 *count = 0;
7814                 *info_p = NULL;
7815                 return result;
7816         }
7817
7818         *info_p = info;
7819         *count = numlines;
7820
7821         return WERR_OK;
7822 }
7823
7824 /****************************************************************************
7825  enumports level 2.
7826 ****************************************************************************/
7827
7828 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7829                                 union spoolss_PortInfo **info_p,
7830                                 uint32_t *count)
7831 {
7832         union spoolss_PortInfo *info = NULL;
7833         int i=0;
7834         WERROR result = WERR_OK;
7835         char **qlines = NULL;
7836         int numlines = 0;
7837
7838         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7839         if (!W_ERROR_IS_OK(result)) {
7840                 goto out;
7841         }
7842
7843         if (numlines) {
7844                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7845                 if (!info) {
7846                         DEBUG(10,("Returning WERR_NOMEM\n"));
7847                         result = WERR_NOMEM;
7848                         goto out;
7849                 }
7850
7851                 for (i=0; i<numlines; i++) {
7852                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7853                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7854                         if (!W_ERROR_IS_OK(result)) {
7855                                 goto out;
7856                         }
7857                 }
7858         }
7859         TALLOC_FREE(qlines);
7860
7861 out:
7862         if (!W_ERROR_IS_OK(result)) {
7863                 TALLOC_FREE(info);
7864                 TALLOC_FREE(qlines);
7865                 *count = 0;
7866                 *info_p = NULL;
7867                 return result;
7868         }
7869
7870         *info_p = info;
7871         *count = numlines;
7872
7873         return WERR_OK;
7874 }
7875
7876 /****************************************************************
7877  _spoolss_EnumPorts
7878 ****************************************************************/
7879
7880 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7881                           struct spoolss_EnumPorts *r)
7882 {
7883         WERROR result;
7884
7885         /* that's an [in out] buffer */
7886
7887         if (!r->in.buffer && (r->in.offered != 0)) {
7888                 return WERR_INVALID_PARAM;
7889         }
7890
7891         DEBUG(4,("_spoolss_EnumPorts\n"));
7892
7893         *r->out.count = 0;
7894         *r->out.needed = 0;
7895         *r->out.info = NULL;
7896
7897         switch (r->in.level) {
7898         case 1:
7899                 result = enumports_level_1(p->mem_ctx, r->out.info,
7900                                            r->out.count);
7901                 break;
7902         case 2:
7903                 result = enumports_level_2(p->mem_ctx, r->out.info,
7904                                            r->out.count);
7905                 break;
7906         default:
7907                 return WERR_UNKNOWN_LEVEL;
7908         }
7909
7910         if (!W_ERROR_IS_OK(result)) {
7911                 return result;
7912         }
7913
7914         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7915                                                      spoolss_EnumPorts,
7916                                                      *r->out.info, r->in.level,
7917                                                      *r->out.count);
7918         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7919         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7920
7921         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7922 }
7923
7924 /****************************************************************************
7925 ****************************************************************************/
7926
7927 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7928                                            const char *server,
7929                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7930                                            struct spoolss_DeviceMode *devmode,
7931                                            struct security_descriptor *secdesc,
7932                                            struct spoolss_UserLevelCtr *user_ctr,
7933                                            struct policy_handle *handle)
7934 {
7935         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7936         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7937         int     snum;
7938         WERROR err = WERR_OK;
7939
7940         /* samba does not have a concept of local, non-shared printers yet, so
7941          * make sure we always setup sharename - gd */
7942         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7943             (info2->printername != NULL && info2->printername[0] != '\0')) {
7944                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7945                         "no sharename has been set, setting printername %s as sharename\n",
7946                         info2->printername));
7947                 info2->sharename = info2->printername;
7948         }
7949
7950         /* check to see if the printer already exists */
7951         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7952                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7953                         info2->sharename));
7954                 return WERR_PRINTER_ALREADY_EXISTS;
7955         }
7956
7957         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7958                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7959                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7960                                 info2->printername));
7961                         return WERR_PRINTER_ALREADY_EXISTS;
7962                 }
7963         }
7964
7965         /* validate printer info struct */
7966         if (!info2->printername || strlen(info2->printername) == 0) {
7967                 return WERR_INVALID_PRINTER_NAME;
7968         }
7969         if (!info2->portname || strlen(info2->portname) == 0) {
7970                 return WERR_UNKNOWN_PORT;
7971         }
7972         if (!info2->drivername || strlen(info2->drivername) == 0) {
7973                 return WERR_UNKNOWN_PRINTER_DRIVER;
7974         }
7975         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7976                 return WERR_UNKNOWN_PRINTPROCESSOR;
7977         }
7978
7979         /* FIXME!!!  smbd should check to see if the driver is installed before
7980            trying to add a printer like this  --jerry */
7981
7982         if (*lp_addprinter_cmd() ) {
7983                 char *raddr;
7984
7985                 raddr = tsocket_address_inet_addr_string(p->remote_address,
7986                                                          p->mem_ctx);
7987                 if (raddr == NULL) {
7988                         return WERR_NOMEM;
7989                 }
7990
7991                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7992                                        info2, raddr,
7993                                        p->msg_ctx) ) {
7994                         return WERR_ACCESS_DENIED;
7995                 }
7996         } else {
7997                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7998                         "smb.conf parameter \"addprinter command\" is defined. This "
7999                         "parameter must exist for this call to succeed\n",
8000                         info2->sharename ));
8001         }
8002
8003         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8004                 return WERR_ACCESS_DENIED;
8005         }
8006
8007         /* you must be a printer admin to add a new printer */
8008         if (!print_access_check(p->session_info,
8009                                 p->msg_ctx,
8010                                 snum,
8011                                 PRINTER_ACCESS_ADMINISTER)) {
8012                 return WERR_ACCESS_DENIED;
8013         }
8014
8015         /*
8016          * Do sanity check on the requested changes for Samba.
8017          */
8018
8019         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8020                 return WERR_INVALID_PARAM;
8021         }
8022
8023         if (devmode == NULL) {
8024                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8025         }
8026
8027         update_dsspooler(p->mem_ctx,
8028                          get_session_info_system(),
8029                          p->msg_ctx,
8030                          0,
8031                          info2,
8032                          NULL);
8033
8034         err = winreg_update_printer_internal(p->mem_ctx,
8035                                     get_session_info_system(),
8036                                     p->msg_ctx,
8037                                     info2->sharename,
8038                                     info2_mask,
8039                                     info2,
8040                                     devmode,
8041                                     secdesc);
8042         if (!W_ERROR_IS_OK(err)) {
8043                 return err;
8044         }
8045
8046         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8047         if (!W_ERROR_IS_OK(err)) {
8048                 /* Handle open failed - remove addition. */
8049                 ZERO_STRUCTP(handle);
8050                 return err;
8051         }
8052
8053         return WERR_OK;
8054 }
8055
8056 /****************************************************************
8057  _spoolss_AddPrinterEx
8058 ****************************************************************/
8059
8060 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8061                              struct spoolss_AddPrinterEx *r)
8062 {
8063         switch (r->in.info_ctr->level) {
8064         case 1:
8065                 /* we don't handle yet */
8066                 /* but I know what to do ... */
8067                 return WERR_UNKNOWN_LEVEL;
8068         case 2:
8069                 return spoolss_addprinterex_level_2(p, r->in.server,
8070                                                     r->in.info_ctr,
8071                                                     r->in.devmode_ctr->devmode,
8072                                                     r->in.secdesc_ctr->sd,
8073                                                     r->in.userlevel_ctr,
8074                                                     r->out.handle);
8075         default:
8076                 return WERR_UNKNOWN_LEVEL;
8077         }
8078 }
8079
8080 /****************************************************************
8081  _spoolss_AddPrinter
8082 ****************************************************************/
8083
8084 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8085                            struct spoolss_AddPrinter *r)
8086 {
8087         struct spoolss_AddPrinterEx a;
8088         struct spoolss_UserLevelCtr userlevel_ctr;
8089
8090         ZERO_STRUCT(userlevel_ctr);
8091
8092         userlevel_ctr.level = 1;
8093
8094         a.in.server             = r->in.server;
8095         a.in.info_ctr           = r->in.info_ctr;
8096         a.in.devmode_ctr        = r->in.devmode_ctr;
8097         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8098         a.in.userlevel_ctr      = &userlevel_ctr;
8099         a.out.handle            = r->out.handle;
8100
8101         return _spoolss_AddPrinterEx(p, &a);
8102 }
8103
8104 /****************************************************************
8105  _spoolss_AddPrinterDriverEx
8106 ****************************************************************/
8107
8108 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8109                                    struct spoolss_AddPrinterDriverEx *r)
8110 {
8111         WERROR err = WERR_OK;
8112         const char *driver_name = NULL;
8113         uint32_t version;
8114         const char *fn;
8115
8116         switch (p->opnum) {
8117                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8118                         fn = "_spoolss_AddPrinterDriver";
8119                         break;
8120                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8121                         fn = "_spoolss_AddPrinterDriverEx";
8122                         break;
8123                 default:
8124                         return WERR_INVALID_PARAM;
8125         }
8126
8127         /*
8128          * we only support the semantics of AddPrinterDriver()
8129          * i.e. only copy files that are newer than existing ones
8130          */
8131
8132         if (r->in.flags == 0) {
8133                 return WERR_INVALID_PARAM;
8134         }
8135
8136         if (r->in.flags != APD_COPY_NEW_FILES) {
8137                 return WERR_ACCESS_DENIED;
8138         }
8139
8140         /* FIXME */
8141         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8142                 /* Clever hack from Martin Zielinski <mz@seh.de>
8143                  * to allow downgrade from level 8 (Vista).
8144                  */
8145                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8146                         r->in.info_ctr->level));
8147                 return WERR_UNKNOWN_LEVEL;
8148         }
8149
8150         DEBUG(5,("Cleaning driver's information\n"));
8151         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8152         if (!W_ERROR_IS_OK(err))
8153                 goto done;
8154
8155         DEBUG(5,("Moving driver to final destination\n"));
8156         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8157         if (!W_ERROR_IS_OK(err)) {
8158                 goto done;
8159         }
8160
8161         err = winreg_add_driver_internal(p->mem_ctx,
8162                                 get_session_info_system(),
8163                                 p->msg_ctx,
8164                                 r->in.info_ctr,
8165                                 &driver_name,
8166                                 &version);
8167         if (!W_ERROR_IS_OK(err)) {
8168                 goto done;
8169         }
8170
8171         /*
8172          * I think this is where he DrvUpgradePrinter() hook would be
8173          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8174          * server.  Right now, we just need to send ourselves a message
8175          * to update each printer bound to this driver.   --jerry
8176          */
8177
8178         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8179                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8180                         fn, driver_name));
8181         }
8182
8183 done:
8184         return err;
8185 }
8186
8187 /****************************************************************
8188  _spoolss_AddPrinterDriver
8189 ****************************************************************/
8190
8191 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8192                                  struct spoolss_AddPrinterDriver *r)
8193 {
8194         struct spoolss_AddPrinterDriverEx a;
8195
8196         switch (r->in.info_ctr->level) {
8197         case 2:
8198         case 3:
8199         case 4:
8200         case 5:
8201                 break;
8202         default:
8203                 return WERR_UNKNOWN_LEVEL;
8204         }
8205
8206         a.in.servername         = r->in.servername;
8207         a.in.info_ctr           = r->in.info_ctr;
8208         a.in.flags              = APD_COPY_NEW_FILES;
8209
8210         return _spoolss_AddPrinterDriverEx(p, &a);
8211 }
8212
8213 /****************************************************************************
8214 ****************************************************************************/
8215
8216 struct _spoolss_paths {
8217         int type;
8218         const char *share;
8219         const char *dir;
8220 };
8221
8222 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8223
8224 static const struct _spoolss_paths spoolss_paths[]= {
8225         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8226         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8227 };
8228
8229 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8230                                           const char *servername,
8231                                           const char *environment,
8232                                           int component,
8233                                           char **path)
8234 {
8235         const char *pservername = NULL;
8236         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8237         const char *short_archi;
8238
8239         *path = NULL;
8240
8241         /* environment may be empty */
8242         if (environment && strlen(environment)) {
8243                 long_archi = environment;
8244         }
8245
8246         /* servername may be empty */
8247         if (servername && strlen(servername)) {
8248                 pservername = canon_servername(servername);
8249
8250                 if (!is_myname_or_ipaddr(pservername)) {
8251                         return WERR_INVALID_PARAM;
8252                 }
8253         }
8254
8255         if (!(short_archi = get_short_archi(long_archi))) {
8256                 return WERR_INVALID_ENVIRONMENT;
8257         }
8258
8259         switch (component) {
8260         case SPOOLSS_PRTPROCS_PATH:
8261         case SPOOLSS_DRIVER_PATH:
8262                 if (pservername) {
8263                         *path = talloc_asprintf(mem_ctx,
8264                                         "\\\\%s\\%s\\%s",
8265                                         pservername,
8266                                         spoolss_paths[component].share,
8267                                         short_archi);
8268                 } else {
8269                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8270                                         SPOOLSS_DEFAULT_SERVER_PATH,
8271                                         spoolss_paths[component].dir,
8272                                         short_archi);
8273                 }
8274                 break;
8275         default:
8276                 return WERR_INVALID_PARAM;
8277         }
8278
8279         if (!*path) {
8280                 return WERR_NOMEM;
8281         }
8282
8283         return WERR_OK;
8284 }
8285
8286 /****************************************************************************
8287 ****************************************************************************/
8288
8289 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8290                                           const char *servername,
8291                                           const char *environment,
8292                                           struct spoolss_DriverDirectoryInfo1 *r)
8293 {
8294         WERROR werr;
8295         char *path = NULL;
8296
8297         werr = compose_spoolss_server_path(mem_ctx,
8298                                            servername,
8299                                            environment,
8300                                            SPOOLSS_DRIVER_PATH,
8301                                            &path);
8302         if (!W_ERROR_IS_OK(werr)) {
8303                 return werr;
8304         }
8305
8306         DEBUG(4,("printer driver directory: [%s]\n", path));
8307
8308         r->directory_name = path;
8309
8310         return WERR_OK;
8311 }
8312
8313 /****************************************************************
8314  _spoolss_GetPrinterDriverDirectory
8315 ****************************************************************/
8316
8317 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8318                                           struct spoolss_GetPrinterDriverDirectory *r)
8319 {
8320         WERROR werror;
8321
8322         /* that's an [in out] buffer */
8323
8324         if (!r->in.buffer && (r->in.offered != 0)) {
8325                 return WERR_INVALID_PARAM;
8326         }
8327
8328         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8329                 r->in.level));
8330
8331         *r->out.needed = 0;
8332
8333         /* r->in.level is ignored */
8334
8335         werror = getprinterdriverdir_level_1(p->mem_ctx,
8336                                              r->in.server,
8337                                              r->in.environment,
8338                                              &r->out.info->info1);
8339         if (!W_ERROR_IS_OK(werror)) {
8340                 TALLOC_FREE(r->out.info);
8341                 return werror;
8342         }
8343
8344         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8345                                                r->out.info, r->in.level);
8346         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8347
8348         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8349 }
8350
8351 /****************************************************************
8352  _spoolss_EnumPrinterData
8353 ****************************************************************/
8354
8355 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8356                                 struct spoolss_EnumPrinterData *r)
8357 {
8358         WERROR result;
8359         struct spoolss_EnumPrinterDataEx r2;
8360         uint32_t count;
8361         struct spoolss_PrinterEnumValues *info, *val = NULL;
8362         uint32_t needed;
8363
8364         r2.in.handle    = r->in.handle;
8365         r2.in.key_name  = "PrinterDriverData";
8366         r2.in.offered   = 0;
8367         r2.out.count    = &count;
8368         r2.out.info     = &info;
8369         r2.out.needed   = &needed;
8370
8371         result = _spoolss_EnumPrinterDataEx(p, &r2);
8372         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8373                 r2.in.offered = needed;
8374                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8375         }
8376         if (!W_ERROR_IS_OK(result)) {
8377                 return result;
8378         }
8379
8380         /*
8381          * The NT machine wants to know the biggest size of value and data
8382          *
8383          * cf: MSDN EnumPrinterData remark section
8384          */
8385
8386         if (!r->in.value_offered && !r->in.data_offered) {
8387                 uint32_t biggest_valuesize = 0;
8388                 uint32_t biggest_datasize = 0;
8389                 int i, name_length;
8390
8391                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8392
8393                 for (i=0; i<count; i++) {
8394
8395                         name_length = strlen(info[i].value_name);
8396                         if (strlen(info[i].value_name) > biggest_valuesize) {
8397                                 biggest_valuesize = name_length;
8398                         }
8399
8400                         if (info[i].data_length > biggest_datasize) {
8401                                 biggest_datasize = info[i].data_length;
8402                         }
8403
8404                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8405                                 biggest_datasize));
8406                 }
8407
8408                 /* the value is an UNICODE string but real_value_size is the length
8409                    in bytes including the trailing 0 */
8410
8411                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8412                 *r->out.data_needed  = biggest_datasize;
8413
8414                 DEBUG(6,("final values: [%d], [%d]\n",
8415                         *r->out.value_needed, *r->out.data_needed));
8416
8417                 return WERR_OK;
8418         }
8419
8420         if (r->in.enum_index < count) {
8421                 val = &info[r->in.enum_index];
8422         }
8423
8424         if (val == NULL) {
8425                 /* out_value should default to "" or else NT4 has
8426                    problems unmarshalling the response */
8427
8428                 if (r->in.value_offered) {
8429                         *r->out.value_needed = 1;
8430                         r->out.value_name = talloc_strdup(r, "");
8431                         if (!r->out.value_name) {
8432                                 return WERR_NOMEM;
8433                         }
8434                 } else {
8435                         r->out.value_name = NULL;
8436                         *r->out.value_needed = 0;
8437                 }
8438
8439                 /* the data is counted in bytes */
8440
8441                 *r->out.data_needed = r->in.data_offered;
8442
8443                 result = WERR_NO_MORE_ITEMS;
8444         } else {
8445                 /*
8446                  * the value is:
8447                  * - counted in bytes in the request
8448                  * - counted in UNICODE chars in the max reply
8449                  * - counted in bytes in the real size
8450                  *
8451                  * take a pause *before* coding not *during* coding
8452                  */
8453
8454                 /* name */
8455                 if (r->in.value_offered) {
8456                         r->out.value_name = talloc_strdup(r, val->value_name);
8457                         if (!r->out.value_name) {
8458                                 return WERR_NOMEM;
8459                         }
8460                         *r->out.value_needed = val->value_name_len;
8461                 } else {
8462                         r->out.value_name = NULL;
8463                         *r->out.value_needed = 0;
8464                 }
8465
8466                 /* type */
8467
8468                 *r->out.type = val->type;
8469
8470                 /* data - counted in bytes */
8471
8472                 /*
8473                  * See the section "Dynamically Typed Query Parameters"
8474                  * in MS-RPRN.
8475                  */
8476
8477                 if (r->out.data && val->data && val->data->data &&
8478                                 val->data_length && r->in.data_offered) {
8479                         memcpy(r->out.data, val->data->data,
8480                                 MIN(val->data_length,r->in.data_offered));
8481                 }
8482
8483                 *r->out.data_needed = val->data_length;
8484
8485                 result = WERR_OK;
8486         }
8487
8488         return result;
8489 }
8490
8491 /****************************************************************
8492  _spoolss_SetPrinterData
8493 ****************************************************************/
8494
8495 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8496                                struct spoolss_SetPrinterData *r)
8497 {
8498         struct spoolss_SetPrinterDataEx r2;
8499
8500         r2.in.handle            = r->in.handle;
8501         r2.in.key_name          = "PrinterDriverData";
8502         r2.in.value_name        = r->in.value_name;
8503         r2.in.type              = r->in.type;
8504         r2.in.data              = r->in.data;
8505         r2.in.offered           = r->in.offered;
8506
8507         return _spoolss_SetPrinterDataEx(p, &r2);
8508 }
8509
8510 /****************************************************************
8511  _spoolss_ResetPrinter
8512 ****************************************************************/
8513
8514 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8515                              struct spoolss_ResetPrinter *r)
8516 {
8517         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8518         int             snum;
8519
8520         DEBUG(5,("_spoolss_ResetPrinter\n"));
8521
8522         /*
8523          * All we do is to check to see if the handle and queue is valid.
8524          * This call really doesn't mean anything to us because we only
8525          * support RAW printing.   --jerry
8526          */
8527
8528         if (!Printer) {
8529                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8530                         OUR_HANDLE(r->in.handle)));
8531                 return WERR_BADFID;
8532         }
8533
8534         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8535                 return WERR_BADFID;
8536
8537
8538         /* blindly return success */
8539         return WERR_OK;
8540 }
8541
8542 /****************************************************************
8543  _spoolss_DeletePrinterData
8544 ****************************************************************/
8545
8546 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8547                                   struct spoolss_DeletePrinterData *r)
8548 {
8549         struct spoolss_DeletePrinterDataEx r2;
8550
8551         r2.in.handle            = r->in.handle;
8552         r2.in.key_name          = "PrinterDriverData";
8553         r2.in.value_name        = r->in.value_name;
8554
8555         return _spoolss_DeletePrinterDataEx(p, &r2);
8556 }
8557
8558 /****************************************************************
8559  _spoolss_AddForm
8560 ****************************************************************/
8561
8562 WERROR _spoolss_AddForm(struct pipes_struct *p,
8563                         struct spoolss_AddForm *r)
8564 {
8565         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8566         int snum = -1;
8567         WERROR status = WERR_OK;
8568         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8569         struct dcerpc_binding_handle *b;
8570         TALLOC_CTX *tmp_ctx = NULL;
8571
8572         DEBUG(5,("_spoolss_AddForm\n"));
8573
8574         if (!Printer) {
8575                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8576                         OUR_HANDLE(r->in.handle)));
8577                 return WERR_BADFID;
8578         }
8579
8580         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8581            and not a printer admin, then fail */
8582
8583         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8584             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8585             !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8586                                           p->session_info->info->domain_name,
8587                                           NULL,
8588                                           p->session_info->security_token,
8589                                           lp_printer_admin(snum))) {
8590                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8591                 return WERR_ACCESS_DENIED;
8592         }
8593
8594         switch (form->flags) {
8595         case SPOOLSS_FORM_USER:
8596         case SPOOLSS_FORM_BUILTIN:
8597         case SPOOLSS_FORM_PRINTER:
8598                 break;
8599         default:
8600                 return WERR_INVALID_PARAM;
8601         }
8602
8603         tmp_ctx = talloc_new(p->mem_ctx);
8604         if (!tmp_ctx) {
8605                 return WERR_NOMEM;
8606         }
8607
8608         status = winreg_printer_binding_handle(tmp_ctx,
8609                                                get_session_info_system(),
8610                                                p->msg_ctx,
8611                                                &b);
8612         if (!W_ERROR_IS_OK(status)) {
8613                 goto done;
8614         }
8615
8616         status = winreg_printer_addform1(tmp_ctx, b, form);
8617         if (!W_ERROR_IS_OK(status)) {
8618                 goto done;
8619         }
8620
8621         /*
8622          * ChangeID must always be set if this is a printer
8623          */
8624         if (Printer->printer_type == SPLHND_PRINTER) {
8625                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8626                         status = WERR_BADFID;
8627                         goto done;
8628                 }
8629
8630                 status = winreg_printer_update_changeid(tmp_ctx, b,
8631                                                         lp_const_servicename(snum));
8632         }
8633
8634 done:
8635         talloc_free(tmp_ctx);
8636         return status;
8637 }
8638
8639 /****************************************************************
8640  _spoolss_DeleteForm
8641 ****************************************************************/
8642
8643 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8644                            struct spoolss_DeleteForm *r)
8645 {
8646         const char *form_name = r->in.form_name;
8647         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8648         int snum = -1;
8649         WERROR status = WERR_OK;
8650         struct dcerpc_binding_handle *b;
8651         TALLOC_CTX *tmp_ctx = NULL;
8652
8653         DEBUG(5,("_spoolss_DeleteForm\n"));
8654
8655         if (!Printer) {
8656                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8657                         OUR_HANDLE(r->in.handle)));
8658                 return WERR_BADFID;
8659         }
8660
8661         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8662             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8663             !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8664                                           p->session_info->info->domain_name,
8665                                           NULL,
8666                                           p->session_info->security_token,
8667                                           lp_printer_admin(snum))) {
8668                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8669                 return WERR_ACCESS_DENIED;
8670         }
8671
8672         tmp_ctx = talloc_new(p->mem_ctx);
8673         if (!tmp_ctx) {
8674                 return WERR_NOMEM;
8675         }
8676
8677         status = winreg_printer_binding_handle(tmp_ctx,
8678                                                get_session_info_system(),
8679                                                p->msg_ctx,
8680                                                &b);
8681         if (!W_ERROR_IS_OK(status)) {
8682                 goto done;
8683         }
8684
8685         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8686         if (!W_ERROR_IS_OK(status)) {
8687                 goto done;
8688         }
8689
8690         /*
8691          * ChangeID must always be set if this is a printer
8692          */
8693         if (Printer->printer_type == SPLHND_PRINTER) {
8694                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8695                         status = WERR_BADFID;
8696                         goto done;
8697                 }
8698
8699                 status = winreg_printer_update_changeid(tmp_ctx, b,
8700                                                         lp_const_servicename(snum));
8701         }
8702
8703 done:
8704         talloc_free(tmp_ctx);
8705         return status;
8706 }
8707
8708 /****************************************************************
8709  _spoolss_SetForm
8710 ****************************************************************/
8711
8712 WERROR _spoolss_SetForm(struct pipes_struct *p,
8713                         struct spoolss_SetForm *r)
8714 {
8715         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8716         const char *form_name = r->in.form_name;
8717         int snum = -1;
8718         WERROR status = WERR_OK;
8719         struct dcerpc_binding_handle *b;
8720         TALLOC_CTX *tmp_ctx = NULL;
8721
8722         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8723
8724         DEBUG(5,("_spoolss_SetForm\n"));
8725
8726         if (!Printer) {
8727                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8728                         OUR_HANDLE(r->in.handle)));
8729                 return WERR_BADFID;
8730         }
8731
8732         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8733            and not a printer admin, then fail */
8734
8735         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8736              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8737              !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8738                                           p->session_info->info->domain_name,
8739                                           NULL,
8740                                           p->session_info->security_token,
8741                                           lp_printer_admin(snum))) {
8742                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8743                 return WERR_ACCESS_DENIED;
8744         }
8745
8746         tmp_ctx = talloc_new(p->mem_ctx);
8747         if (!tmp_ctx) {
8748                 return WERR_NOMEM;
8749         }
8750
8751         status = winreg_printer_binding_handle(tmp_ctx,
8752                                                get_session_info_system(),
8753                                                p->msg_ctx,
8754                                                &b);
8755         if (!W_ERROR_IS_OK(status)) {
8756                 goto done;
8757         }
8758
8759         status = winreg_printer_setform1(tmp_ctx, b,
8760                                          form_name,
8761                                          form);
8762         if (!W_ERROR_IS_OK(status)) {
8763                 goto done;
8764         }
8765
8766         /*
8767          * ChangeID must always be set if this is a printer
8768          */
8769         if (Printer->printer_type == SPLHND_PRINTER) {
8770                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8771                         status = WERR_BADFID;
8772                         goto done;
8773                 }
8774
8775                 status = winreg_printer_update_changeid(tmp_ctx, b,
8776                                                         lp_const_servicename(snum));
8777         }
8778
8779 done:
8780         talloc_free(tmp_ctx);
8781         return status;
8782 }
8783
8784 /****************************************************************************
8785  fill_print_processor1
8786 ****************************************************************************/
8787
8788 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8789                                     struct spoolss_PrintProcessorInfo1 *r,
8790                                     const char *print_processor_name)
8791 {
8792         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8793         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8794
8795         return WERR_OK;
8796 }
8797
8798 /****************************************************************************
8799  enumprintprocessors level 1.
8800 ****************************************************************************/
8801
8802 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8803                                           union spoolss_PrintProcessorInfo **info_p,
8804                                           uint32_t *count)
8805 {
8806         union spoolss_PrintProcessorInfo *info;
8807         WERROR result;
8808
8809         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8810         W_ERROR_HAVE_NO_MEMORY(info);
8811
8812         *count = 1;
8813
8814         result = fill_print_processor1(info, &info[0].info1, "winprint");
8815         if (!W_ERROR_IS_OK(result)) {
8816                 goto out;
8817         }
8818
8819  out:
8820         if (!W_ERROR_IS_OK(result)) {
8821                 TALLOC_FREE(info);
8822                 *count = 0;
8823                 return result;
8824         }
8825
8826         *info_p = info;
8827
8828         return WERR_OK;
8829 }
8830
8831 /****************************************************************
8832  _spoolss_EnumPrintProcessors
8833 ****************************************************************/
8834
8835 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8836                                     struct spoolss_EnumPrintProcessors *r)
8837 {
8838         WERROR result;
8839
8840         /* that's an [in out] buffer */
8841
8842         if (!r->in.buffer && (r->in.offered != 0)) {
8843                 return WERR_INVALID_PARAM;
8844         }
8845
8846         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8847
8848         /*
8849          * Enumerate the print processors ...
8850          *
8851          * Just reply with "winprint", to keep NT happy
8852          * and I can use my nice printer checker.
8853          */
8854
8855         *r->out.count = 0;
8856         *r->out.needed = 0;
8857         *r->out.info = NULL;
8858
8859         if (!get_short_archi(r->in.environment)) {
8860                 return WERR_INVALID_ENVIRONMENT;
8861         }
8862
8863         switch (r->in.level) {
8864         case 1:
8865                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8866                                                      r->out.count);
8867                 break;
8868         default:
8869                 return WERR_UNKNOWN_LEVEL;
8870         }
8871
8872         if (!W_ERROR_IS_OK(result)) {
8873                 return result;
8874         }
8875
8876         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8877                                                      spoolss_EnumPrintProcessors,
8878                                                      *r->out.info, r->in.level,
8879                                                      *r->out.count);
8880         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8881         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8882
8883         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8884 }
8885
8886 /****************************************************************************
8887  fill_printprocdatatype1
8888 ****************************************************************************/
8889
8890 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8891                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8892                                       const char *name_array)
8893 {
8894         r->name_array = talloc_strdup(mem_ctx, name_array);
8895         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8896
8897         return WERR_OK;
8898 }
8899
8900 /****************************************************************************
8901  enumprintprocdatatypes level 1.
8902 ****************************************************************************/
8903
8904 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8905                                              union spoolss_PrintProcDataTypesInfo **info_p,
8906                                              uint32_t *count)
8907 {
8908         WERROR result;
8909         union spoolss_PrintProcDataTypesInfo *info;
8910
8911         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8912         W_ERROR_HAVE_NO_MEMORY(info);
8913
8914         *count = 1;
8915
8916         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8917         if (!W_ERROR_IS_OK(result)) {
8918                 goto out;
8919         }
8920
8921  out:
8922         if (!W_ERROR_IS_OK(result)) {
8923                 TALLOC_FREE(info);
8924                 *count = 0;
8925                 return result;
8926         }
8927
8928         *info_p = info;
8929
8930         return WERR_OK;
8931 }
8932
8933 /****************************************************************
8934  _spoolss_EnumPrintProcDataTypes
8935 ****************************************************************/
8936
8937 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8938                                        struct spoolss_EnumPrintProcDataTypes *r)
8939 {
8940         WERROR result;
8941
8942         /* that's an [in out] buffer */
8943
8944         if (!r->in.buffer && (r->in.offered != 0)) {
8945                 return WERR_INVALID_PARAM;
8946         }
8947
8948         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8949
8950         *r->out.count = 0;
8951         *r->out.needed = 0;
8952         *r->out.info = NULL;
8953
8954         if (r->in.print_processor_name == NULL ||
8955             !strequal(r->in.print_processor_name, "winprint")) {
8956                 return WERR_UNKNOWN_PRINTPROCESSOR;
8957         }
8958
8959         switch (r->in.level) {
8960         case 1:
8961                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8962                                                         r->out.count);
8963                 break;
8964         default:
8965                 return WERR_UNKNOWN_LEVEL;
8966         }
8967
8968         if (!W_ERROR_IS_OK(result)) {
8969                 return result;
8970         }
8971
8972         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8973                                                      spoolss_EnumPrintProcDataTypes,
8974                                                      *r->out.info, r->in.level,
8975                                                      *r->out.count);
8976         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8977         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8978
8979         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8980 }
8981
8982 /****************************************************************************
8983  fill_monitor_1
8984 ****************************************************************************/
8985
8986 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8987                              struct spoolss_MonitorInfo1 *r,
8988                              const char *monitor_name)
8989 {
8990         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8991         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8992
8993         return WERR_OK;
8994 }
8995
8996 /****************************************************************************
8997  fill_monitor_2
8998 ****************************************************************************/
8999
9000 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9001                              struct spoolss_MonitorInfo2 *r,
9002                              const char *monitor_name,
9003                              const char *environment,
9004                              const char *dll_name)
9005 {
9006         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9007         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9008         r->environment                  = talloc_strdup(mem_ctx, environment);
9009         W_ERROR_HAVE_NO_MEMORY(r->environment);
9010         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9011         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9012
9013         return WERR_OK;
9014 }
9015
9016 /****************************************************************************
9017  enumprintmonitors level 1.
9018 ****************************************************************************/
9019
9020 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9021                                         union spoolss_MonitorInfo **info_p,
9022                                         uint32_t *count)
9023 {
9024         union spoolss_MonitorInfo *info;
9025         WERROR result = WERR_OK;
9026
9027         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9028         W_ERROR_HAVE_NO_MEMORY(info);
9029
9030         *count = 2;
9031
9032         result = fill_monitor_1(info, &info[0].info1,
9033                                 SPL_LOCAL_PORT);
9034         if (!W_ERROR_IS_OK(result)) {
9035                 goto out;
9036         }
9037
9038         result = fill_monitor_1(info, &info[1].info1,
9039                                 SPL_TCPIP_PORT);
9040         if (!W_ERROR_IS_OK(result)) {
9041                 goto out;
9042         }
9043
9044 out:
9045         if (!W_ERROR_IS_OK(result)) {
9046                 TALLOC_FREE(info);
9047                 *count = 0;
9048                 return result;
9049         }
9050
9051         *info_p = info;
9052
9053         return WERR_OK;
9054 }
9055
9056 /****************************************************************************
9057  enumprintmonitors level 2.
9058 ****************************************************************************/
9059
9060 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9061                                         union spoolss_MonitorInfo **info_p,
9062                                         uint32_t *count)
9063 {
9064         union spoolss_MonitorInfo *info;
9065         WERROR result = WERR_OK;
9066
9067         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9068         W_ERROR_HAVE_NO_MEMORY(info);
9069
9070         *count = 2;
9071
9072         result = fill_monitor_2(info, &info[0].info2,
9073                                 SPL_LOCAL_PORT,
9074                                 "Windows NT X86", /* FIXME */
9075                                 "localmon.dll");
9076         if (!W_ERROR_IS_OK(result)) {
9077                 goto out;
9078         }
9079
9080         result = fill_monitor_2(info, &info[1].info2,
9081                                 SPL_TCPIP_PORT,
9082                                 "Windows NT X86", /* FIXME */
9083                                 "tcpmon.dll");
9084         if (!W_ERROR_IS_OK(result)) {
9085                 goto out;
9086         }
9087
9088 out:
9089         if (!W_ERROR_IS_OK(result)) {
9090                 TALLOC_FREE(info);
9091                 *count = 0;
9092                 return result;
9093         }
9094
9095         *info_p = info;
9096
9097         return WERR_OK;
9098 }
9099
9100 /****************************************************************
9101  _spoolss_EnumMonitors
9102 ****************************************************************/
9103
9104 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9105                              struct spoolss_EnumMonitors *r)
9106 {
9107         WERROR result;
9108
9109         /* that's an [in out] buffer */
9110
9111         if (!r->in.buffer && (r->in.offered != 0)) {
9112                 return WERR_INVALID_PARAM;
9113         }
9114
9115         DEBUG(5,("_spoolss_EnumMonitors\n"));
9116
9117         /*
9118          * Enumerate the print monitors ...
9119          *
9120          * Just reply with "Local Port", to keep NT happy
9121          * and I can use my nice printer checker.
9122          */
9123
9124         *r->out.count = 0;
9125         *r->out.needed = 0;
9126         *r->out.info = NULL;
9127
9128         switch (r->in.level) {
9129         case 1:
9130                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9131                                                    r->out.count);
9132                 break;
9133         case 2:
9134                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9135                                                    r->out.count);
9136                 break;
9137         default:
9138                 return WERR_UNKNOWN_LEVEL;
9139         }
9140
9141         if (!W_ERROR_IS_OK(result)) {
9142                 return result;
9143         }
9144
9145         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9146                                                      spoolss_EnumMonitors,
9147                                                      *r->out.info, r->in.level,
9148                                                      *r->out.count);
9149         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9150         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9151
9152         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9153 }
9154
9155 /****************************************************************************
9156 ****************************************************************************/
9157
9158 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9159                              const print_queue_struct *queue,
9160                              int count, int snum,
9161                              struct spoolss_PrinterInfo2 *pinfo2,
9162                              uint32_t jobid,
9163                              struct spoolss_JobInfo1 *r)
9164 {
9165         int i = 0;
9166         bool found = false;
9167
9168         for (i=0; i<count; i++) {
9169                 if (queue[i].job == (int)jobid) {
9170                         found = true;
9171                         break;
9172                 }
9173         }
9174
9175         if (found == false) {
9176                 /* NT treats not found as bad param... yet another bad choice */
9177                 return WERR_INVALID_PARAM;
9178         }
9179
9180         return fill_job_info1(mem_ctx,
9181                               r,
9182                               &queue[i],
9183                               i,
9184                               snum,
9185                               pinfo2);
9186 }
9187
9188 /****************************************************************************
9189 ****************************************************************************/
9190
9191 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9192                              const print_queue_struct *queue,
9193                              int count, int snum,
9194                              struct spoolss_PrinterInfo2 *pinfo2,
9195                              uint32_t jobid,
9196                              struct spoolss_JobInfo2 *r)
9197 {
9198         int i = 0;
9199         bool found = false;
9200         struct spoolss_DeviceMode *devmode;
9201         WERROR result;
9202
9203         for (i=0; i<count; i++) {
9204                 if (queue[i].job == (int)jobid) {
9205                         found = true;
9206                         break;
9207                 }
9208         }
9209
9210         if (found == false) {
9211                 /* NT treats not found as bad param... yet another bad
9212                    choice */
9213                 return WERR_INVALID_PARAM;
9214         }
9215
9216         /*
9217          * if the print job does not have a DEVMODE associated with it,
9218          * just use the one for the printer. A NULL devicemode is not
9219          *  a failure condition
9220          */
9221
9222         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9223         if (!devmode) {
9224                 result = spoolss_create_default_devmode(mem_ctx,
9225                                                 pinfo2->printername,
9226                                                 &devmode);
9227                 if (!W_ERROR_IS_OK(result)) {
9228                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9229                         return result;
9230                 }
9231         }
9232
9233         return fill_job_info2(mem_ctx,
9234                               r,
9235                               &queue[i],
9236                               i,
9237                               snum,
9238                               pinfo2,
9239                               devmode);
9240 }
9241
9242 /****************************************************************
9243  _spoolss_GetJob
9244 ****************************************************************/
9245
9246 WERROR _spoolss_GetJob(struct pipes_struct *p,
9247                        struct spoolss_GetJob *r)
9248 {
9249         WERROR result = WERR_OK;
9250         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9251         int snum;
9252         int count;
9253         print_queue_struct      *queue = NULL;
9254         print_status_struct prt_status;
9255
9256         /* that's an [in out] buffer */
9257
9258         if (!r->in.buffer && (r->in.offered != 0)) {
9259                 return WERR_INVALID_PARAM;
9260         }
9261
9262         DEBUG(5,("_spoolss_GetJob\n"));
9263
9264         *r->out.needed = 0;
9265
9266         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9267                 return WERR_BADFID;
9268         }
9269
9270         result = winreg_get_printer_internal(p->mem_ctx,
9271                                     get_session_info_system(),
9272                                     p->msg_ctx,
9273                                     lp_const_servicename(snum),
9274                                     &pinfo2);
9275         if (!W_ERROR_IS_OK(result)) {
9276                 return result;
9277         }
9278
9279         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9280
9281         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9282                      count, prt_status.status, prt_status.message));
9283
9284         switch (r->in.level) {
9285         case 1:
9286                 result = getjob_level_1(p->mem_ctx,
9287                                         queue, count, snum, pinfo2,
9288                                         r->in.job_id, &r->out.info->info1);
9289                 break;
9290         case 2:
9291                 result = getjob_level_2(p->mem_ctx,
9292                                         queue, count, snum, pinfo2,
9293                                         r->in.job_id, &r->out.info->info2);
9294                 break;
9295         default:
9296                 result = WERR_UNKNOWN_LEVEL;
9297                 break;
9298         }
9299
9300         SAFE_FREE(queue);
9301         TALLOC_FREE(pinfo2);
9302
9303         if (!W_ERROR_IS_OK(result)) {
9304                 TALLOC_FREE(r->out.info);
9305                 return result;
9306         }
9307
9308         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9309                                                                                    r->in.level);
9310         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9311
9312         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9313 }
9314
9315 /****************************************************************
9316  _spoolss_GetPrinterDataEx
9317 ****************************************************************/
9318
9319 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9320                                  struct spoolss_GetPrinterDataEx *r)
9321 {
9322
9323         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9324         const char *printer;
9325         int                     snum = 0;
9326         WERROR result = WERR_OK;
9327         DATA_BLOB blob;
9328         enum winreg_Type val_type = REG_NONE;
9329         uint8_t *val_data = NULL;
9330         uint32_t val_size = 0;
9331         struct dcerpc_binding_handle *b;
9332         TALLOC_CTX *tmp_ctx;
9333
9334         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9335
9336         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9337                 r->in.key_name, r->in.value_name));
9338
9339         /* in case of problem, return some default values */
9340
9341         *r->out.needed  = 0;
9342         *r->out.type    = REG_NONE;
9343
9344         tmp_ctx = talloc_new(p->mem_ctx);
9345         if (!tmp_ctx) {
9346                 return WERR_NOMEM;
9347         }
9348
9349         if (!Printer) {
9350                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9351                         OUR_HANDLE(r->in.handle)));
9352                 result = WERR_BADFID;
9353                 goto done;
9354         }
9355
9356         /* check to see if the keyname is valid */
9357         if (!strlen(r->in.key_name)) {
9358                 result = WERR_INVALID_PARAM;
9359                 goto done;
9360         }
9361
9362         /* Is the handle to a printer or to the server? */
9363
9364         if (Printer->printer_type == SPLHND_SERVER) {
9365
9366                 union spoolss_PrinterData data;
9367
9368                 result = getprinterdata_printer_server(tmp_ctx,
9369                                                        r->in.value_name,
9370                                                        r->out.type,
9371                                                        &data);
9372                 if (!W_ERROR_IS_OK(result)) {
9373                         goto done;
9374                 }
9375
9376                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9377                                                   *r->out.type, &data);
9378                 if (!W_ERROR_IS_OK(result)) {
9379                         goto done;
9380                 }
9381
9382                 *r->out.needed = blob.length;
9383
9384                 if (r->in.offered >= *r->out.needed) {
9385                         memcpy(r->out.data, blob.data, blob.length);
9386                 }
9387
9388                 result = WERR_OK;
9389                 goto done;
9390         }
9391
9392         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9393                 result = WERR_BADFID;
9394                 goto done;
9395         }
9396         printer = lp_const_servicename(snum);
9397
9398         result = winreg_printer_binding_handle(tmp_ctx,
9399                                                get_session_info_system(),
9400                                                p->msg_ctx,
9401                                                &b);
9402         if (!W_ERROR_IS_OK(result)) {
9403                 goto done;
9404         }
9405
9406         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9407         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9408             strequal(r->in.value_name, "ChangeId")) {
9409                 *r->out.type = REG_DWORD;
9410                 *r->out.needed = 4;
9411                 if (r->in.offered >= *r->out.needed) {
9412                         uint32_t changeid = 0;
9413
9414                         result = winreg_printer_get_changeid(tmp_ctx, b,
9415                                                              printer,
9416                                                              &changeid);
9417                         if (!W_ERROR_IS_OK(result)) {
9418                                 goto done;
9419                         }
9420
9421                         SIVAL(r->out.data, 0, changeid);
9422                         result = WERR_OK;
9423                 }
9424                 goto done;
9425         }
9426
9427         result = winreg_get_printer_dataex(tmp_ctx, b,
9428                                            printer,
9429                                            r->in.key_name,
9430                                            r->in.value_name,
9431                                            &val_type,
9432                                            &val_data,
9433                                            &val_size);
9434         if (!W_ERROR_IS_OK(result)) {
9435                 goto done;
9436         }
9437
9438         *r->out.needed = val_size;
9439         *r->out.type = val_type;
9440
9441         if (r->in.offered >= *r->out.needed) {
9442                 memcpy(r->out.data, val_data, val_size);
9443         }
9444
9445 done:
9446         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9447
9448         if (W_ERROR_IS_OK(result)) {
9449                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9450         }
9451
9452         talloc_free(tmp_ctx);
9453         return result;
9454 }
9455
9456 /****************************************************************
9457  _spoolss_SetPrinterDataEx
9458 ****************************************************************/
9459
9460 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9461                                  struct spoolss_SetPrinterDataEx *r)
9462 {
9463         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9464         int                     snum = 0;
9465         WERROR                  result = WERR_OK;
9466         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9467         char                    *oid_string;
9468         struct dcerpc_binding_handle *b;
9469         TALLOC_CTX *tmp_ctx;
9470
9471         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9472
9473         /* From MSDN documentation of SetPrinterDataEx: pass request to
9474            SetPrinterData if key is "PrinterDriverData" */
9475
9476         if (!Printer) {
9477                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9478                         OUR_HANDLE(r->in.handle)));
9479                 return WERR_BADFID;
9480         }
9481
9482         if (Printer->printer_type == SPLHND_SERVER) {
9483                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9484                         "Not implemented for server handles yet\n"));
9485                 return WERR_INVALID_PARAM;
9486         }
9487
9488         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9489                 return WERR_BADFID;
9490         }
9491
9492         /*
9493          * Access check : NT returns "access denied" if you make a
9494          * SetPrinterData call without the necessary privildge.
9495          * we were originally returning OK if nothing changed
9496          * which made Win2k issue **a lot** of SetPrinterData
9497          * when connecting to a printer  --jerry
9498          */
9499
9500         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9501                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9502                         "change denied by handle access permissions\n"));
9503                 return WERR_ACCESS_DENIED;
9504         }
9505
9506         tmp_ctx = talloc_new(p->mem_ctx);
9507         if (!tmp_ctx) {
9508                 return WERR_NOMEM;
9509         }
9510
9511         result = winreg_printer_binding_handle(tmp_ctx,
9512                                                get_session_info_system(),
9513                                                p->msg_ctx,
9514                                                &b);
9515         if (!W_ERROR_IS_OK(result)) {
9516                 goto done;
9517         }
9518
9519         result = winreg_get_printer(tmp_ctx, b,
9520                                     lp_servicename(snum),
9521                                     &pinfo2);
9522         if (!W_ERROR_IS_OK(result)) {
9523                 goto done;
9524         }
9525
9526         /* check for OID in valuename */
9527
9528         oid_string = strchr(r->in.value_name, ',');
9529         if (oid_string) {
9530                 *oid_string = '\0';
9531                 oid_string++;
9532         }
9533
9534         /* save the registry data */
9535
9536         result = winreg_set_printer_dataex(tmp_ctx, b,
9537                                            pinfo2->sharename,
9538                                            r->in.key_name,
9539                                            r->in.value_name,
9540                                            r->in.type,
9541                                            r->in.data,
9542                                            r->in.offered);
9543
9544         if (W_ERROR_IS_OK(result)) {
9545                 /* save the OID if one was specified */
9546                 if (oid_string) {
9547                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9548                                 r->in.key_name, SPOOL_OID_KEY);
9549                         if (!str) {
9550                                 result = WERR_NOMEM;
9551                                 goto done;
9552                         }
9553
9554                         /*
9555                          * I'm not checking the status here on purpose.  Don't know
9556                          * if this is right, but I'm returning the status from the
9557                          * previous set_printer_dataex() call.  I have no idea if
9558                          * this is right.    --jerry
9559                          */
9560                         winreg_set_printer_dataex(tmp_ctx, b,
9561                                                   pinfo2->sharename,
9562                                                   str,
9563                                                   r->in.value_name,
9564                                                   REG_SZ,
9565                                                   (uint8_t *) oid_string,
9566                                                   strlen(oid_string) + 1);
9567                 }
9568
9569                 result = winreg_printer_update_changeid(tmp_ctx, b,
9570                                                         lp_const_servicename(snum));
9571
9572         }
9573
9574 done:
9575         talloc_free(tmp_ctx);
9576         return result;
9577 }
9578
9579 /****************************************************************
9580  _spoolss_DeletePrinterDataEx
9581 ****************************************************************/
9582
9583 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9584                                     struct spoolss_DeletePrinterDataEx *r)
9585 {
9586         const char *printer;
9587         int             snum=0;
9588         WERROR          status = WERR_OK;
9589         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9590
9591         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9592
9593         if (!Printer) {
9594                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9595                         "Invalid handle (%s:%u:%u).\n",
9596                         OUR_HANDLE(r->in.handle)));
9597                 return WERR_BADFID;
9598         }
9599
9600         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9601                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9602                         "printer properties change denied by handle\n"));
9603                 return WERR_ACCESS_DENIED;
9604         }
9605
9606         if (!r->in.value_name || !r->in.key_name) {
9607                 return WERR_NOMEM;
9608         }
9609
9610         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9611                 return WERR_BADFID;
9612         }
9613         printer = lp_const_servicename(snum);
9614
9615         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9616                                               get_session_info_system(),
9617                                               p->msg_ctx,
9618                                               printer,
9619                                               r->in.key_name,
9620                                               r->in.value_name);
9621         if (W_ERROR_IS_OK(status)) {
9622                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9623                                                         get_session_info_system(),
9624                                                         p->msg_ctx,
9625                                                         printer);
9626         }
9627
9628         return status;
9629 }
9630
9631 /****************************************************************
9632  _spoolss_EnumPrinterKey
9633 ****************************************************************/
9634
9635 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9636                                struct spoolss_EnumPrinterKey *r)
9637 {
9638         uint32_t        num_keys;
9639         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9640         int             snum = 0;
9641         WERROR          result = WERR_BADFILE;
9642         const char **array = NULL;
9643         DATA_BLOB blob;
9644
9645         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9646
9647         if (!Printer) {
9648                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9649                         OUR_HANDLE(r->in.handle)));
9650                 return WERR_BADFID;
9651         }
9652
9653         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9654                 return WERR_BADFID;
9655         }
9656
9657         result = winreg_enum_printer_key_internal(p->mem_ctx,
9658                                          get_session_info_system(),
9659                                          p->msg_ctx,
9660                                          lp_const_servicename(snum),
9661                                          r->in.key_name,
9662                                          &num_keys,
9663                                          &array);
9664         if (!W_ERROR_IS_OK(result)) {
9665                 goto done;
9666         }
9667
9668         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9669                 result = WERR_NOMEM;
9670                 goto done;
9671         }
9672
9673         *r->out._ndr_size = r->in.offered / 2;
9674         *r->out.needed = blob.length;
9675
9676         if (r->in.offered < *r->out.needed) {
9677                 result = WERR_MORE_DATA;
9678         } else {
9679                 result = WERR_OK;
9680                 r->out.key_buffer->string_array = array;
9681         }
9682
9683  done:
9684         if (!W_ERROR_IS_OK(result)) {
9685                 TALLOC_FREE(array);
9686                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9687                         *r->out.needed = 0;
9688                 }
9689         }
9690
9691         return result;
9692 }
9693
9694 /****************************************************************
9695  _spoolss_DeletePrinterKey
9696 ****************************************************************/
9697
9698 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9699                                  struct spoolss_DeletePrinterKey *r)
9700 {
9701         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9702         int                     snum=0;
9703         WERROR                  status;
9704         const char *printer;
9705         struct dcerpc_binding_handle *b;
9706         TALLOC_CTX *tmp_ctx;
9707
9708         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9709
9710         if (!Printer) {
9711                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9712                         OUR_HANDLE(r->in.handle)));
9713                 return WERR_BADFID;
9714         }
9715
9716         /* if keyname == NULL, return error */
9717         if ( !r->in.key_name )
9718                 return WERR_INVALID_PARAM;
9719
9720         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9721                 return WERR_BADFID;
9722         }
9723
9724         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9725                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9726                         "printer properties change denied by handle\n"));
9727                 return WERR_ACCESS_DENIED;
9728         }
9729
9730         printer = lp_const_servicename(snum);
9731
9732         tmp_ctx = talloc_new(p->mem_ctx);
9733         if (!tmp_ctx) {
9734                 return WERR_NOMEM;
9735         }
9736
9737         status = winreg_printer_binding_handle(tmp_ctx,
9738                                                get_session_info_system(),
9739                                                p->msg_ctx,
9740                                                &b);
9741         if (!W_ERROR_IS_OK(status)) {
9742                 goto done;
9743         }
9744
9745         /* delete the key and all subkeys */
9746         status = winreg_delete_printer_key(tmp_ctx, b,
9747                                            printer,
9748                                            r->in.key_name);
9749         if (W_ERROR_IS_OK(status)) {
9750                 status = winreg_printer_update_changeid(tmp_ctx, b,
9751                                                         printer);
9752         }
9753
9754 done:
9755         talloc_free(tmp_ctx);
9756         return status;
9757 }
9758
9759 /****************************************************************
9760  _spoolss_EnumPrinterDataEx
9761 ****************************************************************/
9762
9763 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9764                                   struct spoolss_EnumPrinterDataEx *r)
9765 {
9766         uint32_t        count = 0;
9767         struct spoolss_PrinterEnumValues *info = NULL;
9768         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9769         int             snum;
9770         WERROR          result;
9771
9772         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9773
9774         *r->out.count = 0;
9775         *r->out.needed = 0;
9776         *r->out.info = NULL;
9777
9778         if (!Printer) {
9779                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9780                         OUR_HANDLE(r->in.handle)));
9781                 return WERR_BADFID;
9782         }
9783
9784         /*
9785          * first check for a keyname of NULL or "".  Win2k seems to send
9786          * this a lot and we should send back WERR_INVALID_PARAM
9787          * no need to spend time looking up the printer in this case.
9788          * --jerry
9789          */
9790
9791         if (!strlen(r->in.key_name)) {
9792                 result = WERR_INVALID_PARAM;
9793                 goto done;
9794         }
9795
9796         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9797                 return WERR_BADFID;
9798         }
9799
9800         /* now look for a match on the key name */
9801         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9802                                             get_session_info_system(),
9803                                             p->msg_ctx,
9804                                             lp_const_servicename(snum),
9805                                             r->in.key_name,
9806                                             &count,
9807                                             &info);
9808         if (!W_ERROR_IS_OK(result)) {
9809                 goto done;
9810         }
9811
9812 #if 0 /* FIXME - gd */
9813         /* housekeeping information in the reply */
9814
9815         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9816          * the hand marshalled container size is a multiple
9817          * of 4 bytes for RPC alignment.
9818          */
9819
9820         if (needed % 4) {
9821                 needed += 4-(needed % 4);
9822         }
9823 #endif
9824         *r->out.count   = count;
9825         *r->out.info    = info;
9826
9827  done:
9828         if (!W_ERROR_IS_OK(result)) {
9829                 return result;
9830         }
9831
9832         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9833                                                spoolss_EnumPrinterDataEx,
9834                                                *r->out.info,
9835                                                *r->out.count);
9836         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9837         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9838
9839         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9840 }
9841
9842 /****************************************************************************
9843 ****************************************************************************/
9844
9845 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9846                                                  const char *servername,
9847                                                  const char *environment,
9848                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9849 {
9850         WERROR werr;
9851         char *path = NULL;
9852
9853         werr = compose_spoolss_server_path(mem_ctx,
9854                                            servername,
9855                                            environment,
9856                                            SPOOLSS_PRTPROCS_PATH,
9857                                            &path);
9858         if (!W_ERROR_IS_OK(werr)) {
9859                 return werr;
9860         }
9861
9862         DEBUG(4,("print processor directory: [%s]\n", path));
9863
9864         r->directory_name = path;
9865
9866         return WERR_OK;
9867 }
9868
9869 /****************************************************************
9870  _spoolss_GetPrintProcessorDirectory
9871 ****************************************************************/
9872
9873 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9874                                            struct spoolss_GetPrintProcessorDirectory *r)
9875 {
9876         WERROR result;
9877         char *prnproc_share = NULL;
9878         bool prnproc_share_exists = false;
9879         int snum;
9880
9881         /* that's an [in out] buffer */
9882
9883         if (!r->in.buffer && (r->in.offered != 0)) {
9884                 return WERR_INVALID_PARAM;
9885         }
9886
9887         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9888                 r->in.level));
9889
9890         *r->out.needed = 0;
9891
9892         /* r->in.level is ignored */
9893
9894         /* We always should reply with a local print processor directory so that
9895          * users are not forced to have a [prnproc$] share on the Samba spoolss
9896          * server, if users decide to do so, lets announce it though - Guenther */
9897
9898         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9899         if (!prnproc_share) {
9900                 return WERR_NOMEM;
9901         }
9902         if (snum != -1) {
9903                 prnproc_share_exists = true;
9904         }
9905
9906         result = getprintprocessordirectory_level_1(p->mem_ctx,
9907                                                     prnproc_share_exists ? r->in.server : NULL,
9908                                                     r->in.environment,
9909                                                     &r->out.info->info1);
9910         if (!W_ERROR_IS_OK(result)) {
9911                 TALLOC_FREE(r->out.info);
9912                 return result;
9913         }
9914
9915         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9916                                                                                    r->out.info, r->in.level);
9917         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9918
9919         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9920 }
9921
9922 /*******************************************************************
9923  ********************************************************************/
9924
9925 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9926                                const char *dllname)
9927 {
9928         enum ndr_err_code ndr_err;
9929         struct spoolss_MonitorUi ui;
9930
9931         ui.dll_name = dllname;
9932
9933         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9934                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9935         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9936                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9937         }
9938         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9939 }
9940
9941 /*******************************************************************
9942  Streams the monitor UI DLL name in UNICODE
9943 *******************************************************************/
9944
9945 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9946                                struct security_token *token, DATA_BLOB *in,
9947                                DATA_BLOB *out, uint32_t *needed)
9948 {
9949         const char *dllname = "tcpmonui.dll";
9950
9951         *needed = (strlen(dllname)+1) * 2;
9952
9953         if (out->length < *needed) {
9954                 return WERR_INSUFFICIENT_BUFFER;
9955         }
9956
9957         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9958                 return WERR_NOMEM;
9959         }
9960
9961         return WERR_OK;
9962 }
9963
9964 /*******************************************************************
9965  ********************************************************************/
9966
9967 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9968                              struct spoolss_PortData1 *port1,
9969                              const DATA_BLOB *buf)
9970 {
9971         enum ndr_err_code ndr_err;
9972         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9973                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9974         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9975                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9976         }
9977         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9978 }
9979
9980 /*******************************************************************
9981  ********************************************************************/
9982
9983 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9984                              struct spoolss_PortData2 *port2,
9985                              const DATA_BLOB *buf)
9986 {
9987         enum ndr_err_code ndr_err;
9988         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9989                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9990         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9991                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9992         }
9993         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9994 }
9995
9996 /*******************************************************************
9997  Create a new TCP/IP port
9998 *******************************************************************/
9999
10000 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10001                              struct security_token *token, DATA_BLOB *in,
10002                              DATA_BLOB *out, uint32_t *needed)
10003 {
10004         struct spoolss_PortData1 port1;
10005         struct spoolss_PortData2 port2;
10006         char *device_uri = NULL;
10007         uint32_t version;
10008
10009         const char *portname;
10010         const char *hostaddress;
10011         const char *queue;
10012         uint32_t port_number;
10013         uint32_t protocol;
10014
10015         /* peek for spoolss_PortData version */
10016
10017         if (!in || (in->length < (128 + 4))) {
10018                 return WERR_GENERAL_FAILURE;
10019         }
10020
10021         version = IVAL(in->data, 128);
10022
10023         switch (version) {
10024                 case 1:
10025                         ZERO_STRUCT(port1);
10026
10027                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10028                                 return WERR_NOMEM;
10029                         }
10030
10031                         portname        = port1.portname;
10032                         hostaddress     = port1.hostaddress;
10033                         queue           = port1.queue;
10034                         protocol        = port1.protocol;
10035                         port_number     = port1.port_number;
10036
10037                         break;
10038                 case 2:
10039                         ZERO_STRUCT(port2);
10040
10041                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10042                                 return WERR_NOMEM;
10043                         }
10044
10045                         portname        = port2.portname;
10046                         hostaddress     = port2.hostaddress;
10047                         queue           = port2.queue;
10048                         protocol        = port2.protocol;
10049                         port_number     = port2.port_number;
10050
10051                         break;
10052                 default:
10053                         DEBUG(1,("xcvtcp_addport: "
10054                                 "unknown version of port_data: %d\n", version));
10055                         return WERR_UNKNOWN_PORT;
10056         }
10057
10058         /* create the device URI and call the add_port_hook() */
10059
10060         switch (protocol) {
10061         case PROTOCOL_RAWTCP_TYPE:
10062                 device_uri = talloc_asprintf(mem_ctx,
10063                                 "socket://%s:%d/", hostaddress,
10064                                 port_number);
10065                 break;
10066
10067         case PROTOCOL_LPR_TYPE:
10068                 device_uri = talloc_asprintf(mem_ctx,
10069                         "lpr://%s/%s", hostaddress, queue );
10070                 break;
10071
10072         default:
10073                 return WERR_UNKNOWN_PORT;
10074         }
10075
10076         if (!device_uri) {
10077                 return WERR_NOMEM;
10078         }
10079
10080         return add_port_hook(mem_ctx, token, portname, device_uri);
10081 }
10082
10083 /*******************************************************************
10084 *******************************************************************/
10085
10086 struct xcv_api_table xcvtcp_cmds[] = {
10087         { "MonitorUI",  xcvtcp_monitorui },
10088         { "AddPort",    xcvtcp_addport},
10089         { NULL,         NULL }
10090 };
10091
10092 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10093                                      struct security_token *token, const char *command,
10094                                      DATA_BLOB *inbuf,
10095                                      DATA_BLOB *outbuf,
10096                                      uint32_t *needed )
10097 {
10098         int i;
10099
10100         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10101
10102         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10103                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10104                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10105         }
10106
10107         return WERR_BADFUNC;
10108 }
10109
10110 /*******************************************************************
10111 *******************************************************************/
10112 #if 0   /* don't support management using the "Local Port" monitor */
10113
10114 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10115                                  struct security_token *token, DATA_BLOB *in,
10116                                  DATA_BLOB *out, uint32_t *needed)
10117 {
10118         const char *dllname = "localui.dll";
10119
10120         *needed = (strlen(dllname)+1) * 2;
10121
10122         if (out->length < *needed) {
10123                 return WERR_INSUFFICIENT_BUFFER;
10124         }
10125
10126         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10127                 return WERR_NOMEM;
10128         }
10129
10130         return WERR_OK;
10131 }
10132
10133 /*******************************************************************
10134 *******************************************************************/
10135
10136 struct xcv_api_table xcvlocal_cmds[] = {
10137         { "MonitorUI",  xcvlocal_monitorui },
10138         { NULL,         NULL }
10139 };
10140 #else
10141 struct xcv_api_table xcvlocal_cmds[] = {
10142         { NULL,         NULL }
10143 };
10144 #endif
10145
10146
10147
10148 /*******************************************************************
10149 *******************************************************************/
10150
10151 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10152                                        struct security_token *token, const char *command,
10153                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10154                                        uint32_t *needed)
10155 {
10156         int i;
10157
10158         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10159
10160         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10161                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10162                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10163         }
10164         return WERR_BADFUNC;
10165 }
10166
10167 /****************************************************************
10168  _spoolss_XcvData
10169 ****************************************************************/
10170
10171 WERROR _spoolss_XcvData(struct pipes_struct *p,
10172                         struct spoolss_XcvData *r)
10173 {
10174         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10175         DATA_BLOB out_data = data_blob_null;
10176         WERROR werror;
10177
10178         if (!Printer) {
10179                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10180                         OUR_HANDLE(r->in.handle)));
10181                 return WERR_BADFID;
10182         }
10183
10184         /* Has to be a handle to the TCP/IP port monitor */
10185
10186         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10187                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10188                 return WERR_BADFID;
10189         }
10190
10191         /* requires administrative access to the server */
10192
10193         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10194                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10195                 return WERR_ACCESS_DENIED;
10196         }
10197
10198         /* Allocate the outgoing buffer */
10199
10200         if (r->in.out_data_size) {
10201                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10202                 if (out_data.data == NULL) {
10203                         return WERR_NOMEM;
10204                 }
10205         }
10206
10207         switch ( Printer->printer_type ) {
10208         case SPLHND_PORTMON_TCP:
10209                 werror = process_xcvtcp_command(p->mem_ctx,
10210                                                 p->session_info->security_token,
10211                                                 r->in.function_name,
10212                                                 &r->in.in_data, &out_data,
10213                                                 r->out.needed);
10214                 break;
10215         case SPLHND_PORTMON_LOCAL:
10216                 werror = process_xcvlocal_command(p->mem_ctx,
10217                                                   p->session_info->security_token,
10218                                                   r->in.function_name,
10219                                                   &r->in.in_data, &out_data,
10220                                                   r->out.needed);
10221                 break;
10222         default:
10223                 werror = WERR_INVALID_PRINT_MONITOR;
10224         }
10225
10226         if (!W_ERROR_IS_OK(werror)) {
10227                 return werror;
10228         }
10229
10230         *r->out.status_code = 0;
10231
10232         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10233                 memcpy(r->out.out_data, out_data.data,
10234                         MIN(r->in.out_data_size, out_data.length));
10235         }
10236
10237         return WERR_OK;
10238 }
10239
10240 /****************************************************************
10241  _spoolss_AddPrintProcessor
10242 ****************************************************************/
10243
10244 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10245                                   struct spoolss_AddPrintProcessor *r)
10246 {
10247         /* for now, just indicate success and ignore the add.  We'll
10248            automatically set the winprint processor for printer
10249            entries later.  Used to debug the LexMark Optra S 1855 PCL
10250            driver --jerry */
10251
10252         return WERR_OK;
10253 }
10254
10255 /****************************************************************
10256  _spoolss_AddPort
10257 ****************************************************************/
10258
10259 WERROR _spoolss_AddPort(struct pipes_struct *p,
10260                         struct spoolss_AddPort *r)
10261 {
10262         /* do what w2k3 does */
10263
10264         return WERR_NOT_SUPPORTED;
10265 }
10266
10267 /****************************************************************
10268  _spoolss_GetPrinterDriver
10269 ****************************************************************/
10270
10271 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10272                                  struct spoolss_GetPrinterDriver *r)
10273 {
10274         p->rng_fault_state = true;
10275         return WERR_NOT_SUPPORTED;
10276 }
10277
10278 /****************************************************************
10279  _spoolss_ReadPrinter
10280 ****************************************************************/
10281
10282 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10283                             struct spoolss_ReadPrinter *r)
10284 {
10285         p->rng_fault_state = true;
10286         return WERR_NOT_SUPPORTED;
10287 }
10288
10289 /****************************************************************
10290  _spoolss_WaitForPrinterChange
10291 ****************************************************************/
10292
10293 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10294                                      struct spoolss_WaitForPrinterChange *r)
10295 {
10296         p->rng_fault_state = true;
10297         return WERR_NOT_SUPPORTED;
10298 }
10299
10300 /****************************************************************
10301  _spoolss_ConfigurePort
10302 ****************************************************************/
10303
10304 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10305                               struct spoolss_ConfigurePort *r)
10306 {
10307         p->rng_fault_state = true;
10308         return WERR_NOT_SUPPORTED;
10309 }
10310
10311 /****************************************************************
10312  _spoolss_DeletePort
10313 ****************************************************************/
10314
10315 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10316                            struct spoolss_DeletePort *r)
10317 {
10318         p->rng_fault_state = true;
10319         return WERR_NOT_SUPPORTED;
10320 }
10321
10322 /****************************************************************
10323  _spoolss_CreatePrinterIC
10324 ****************************************************************/
10325
10326 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10327                                 struct spoolss_CreatePrinterIC *r)
10328 {
10329         p->rng_fault_state = true;
10330         return WERR_NOT_SUPPORTED;
10331 }
10332
10333 /****************************************************************
10334  _spoolss_PlayGDIScriptOnPrinterIC
10335 ****************************************************************/
10336
10337 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10338                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10339 {
10340         p->rng_fault_state = true;
10341         return WERR_NOT_SUPPORTED;
10342 }
10343
10344 /****************************************************************
10345  _spoolss_DeletePrinterIC
10346 ****************************************************************/
10347
10348 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10349                                 struct spoolss_DeletePrinterIC *r)
10350 {
10351         p->rng_fault_state = true;
10352         return WERR_NOT_SUPPORTED;
10353 }
10354
10355 /****************************************************************
10356  _spoolss_AddPrinterConnection
10357 ****************************************************************/
10358
10359 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10360                                      struct spoolss_AddPrinterConnection *r)
10361 {
10362         p->rng_fault_state = true;
10363         return WERR_NOT_SUPPORTED;
10364 }
10365
10366 /****************************************************************
10367  _spoolss_DeletePrinterConnection
10368 ****************************************************************/
10369
10370 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10371                                         struct spoolss_DeletePrinterConnection *r)
10372 {
10373         p->rng_fault_state = true;
10374         return WERR_NOT_SUPPORTED;
10375 }
10376
10377 /****************************************************************
10378  _spoolss_PrinterMessageBox
10379 ****************************************************************/
10380
10381 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10382                                   struct spoolss_PrinterMessageBox *r)
10383 {
10384         p->rng_fault_state = true;
10385         return WERR_NOT_SUPPORTED;
10386 }
10387
10388 /****************************************************************
10389  _spoolss_AddMonitor
10390 ****************************************************************/
10391
10392 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10393                            struct spoolss_AddMonitor *r)
10394 {
10395         p->rng_fault_state = true;
10396         return WERR_NOT_SUPPORTED;
10397 }
10398
10399 /****************************************************************
10400  _spoolss_DeleteMonitor
10401 ****************************************************************/
10402
10403 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10404                               struct spoolss_DeleteMonitor *r)
10405 {
10406         p->rng_fault_state = true;
10407         return WERR_NOT_SUPPORTED;
10408 }
10409
10410 /****************************************************************
10411  _spoolss_DeletePrintProcessor
10412 ****************************************************************/
10413
10414 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10415                                      struct spoolss_DeletePrintProcessor *r)
10416 {
10417         p->rng_fault_state = true;
10418         return WERR_NOT_SUPPORTED;
10419 }
10420
10421 /****************************************************************
10422  _spoolss_AddPrintProvidor
10423 ****************************************************************/
10424
10425 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10426                                  struct spoolss_AddPrintProvidor *r)
10427 {
10428         p->rng_fault_state = true;
10429         return WERR_NOT_SUPPORTED;
10430 }
10431
10432 /****************************************************************
10433  _spoolss_DeletePrintProvidor
10434 ****************************************************************/
10435
10436 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10437                                     struct spoolss_DeletePrintProvidor *r)
10438 {
10439         p->rng_fault_state = true;
10440         return WERR_NOT_SUPPORTED;
10441 }
10442
10443 /****************************************************************
10444  _spoolss_FindFirstPrinterChangeNotification
10445 ****************************************************************/
10446
10447 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10448                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10449 {
10450         p->rng_fault_state = true;
10451         return WERR_NOT_SUPPORTED;
10452 }
10453
10454 /****************************************************************
10455  _spoolss_FindNextPrinterChangeNotification
10456 ****************************************************************/
10457
10458 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10459                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10460 {
10461         p->rng_fault_state = true;
10462         return WERR_NOT_SUPPORTED;
10463 }
10464
10465 /****************************************************************
10466  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10467 ****************************************************************/
10468
10469 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10470                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10471 {
10472         p->rng_fault_state = true;
10473         return WERR_NOT_SUPPORTED;
10474 }
10475
10476 /****************************************************************
10477  _spoolss_ReplyOpenPrinter
10478 ****************************************************************/
10479
10480 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10481                                  struct spoolss_ReplyOpenPrinter *r)
10482 {
10483         p->rng_fault_state = true;
10484         return WERR_NOT_SUPPORTED;
10485 }
10486
10487 /****************************************************************
10488  _spoolss_RouterReplyPrinter
10489 ****************************************************************/
10490
10491 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10492                                    struct spoolss_RouterReplyPrinter *r)
10493 {
10494         p->rng_fault_state = true;
10495         return WERR_NOT_SUPPORTED;
10496 }
10497
10498 /****************************************************************
10499  _spoolss_ReplyClosePrinter
10500 ****************************************************************/
10501
10502 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10503                                   struct spoolss_ReplyClosePrinter *r)
10504 {
10505         p->rng_fault_state = true;
10506         return WERR_NOT_SUPPORTED;
10507 }
10508
10509 /****************************************************************
10510  _spoolss_AddPortEx
10511 ****************************************************************/
10512
10513 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10514                           struct spoolss_AddPortEx *r)
10515 {
10516         p->rng_fault_state = true;
10517         return WERR_NOT_SUPPORTED;
10518 }
10519
10520 /****************************************************************
10521  _spoolss_RouterFindFirstPrinterChangeNotification
10522 ****************************************************************/
10523
10524 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10525                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10526 {
10527         p->rng_fault_state = true;
10528         return WERR_NOT_SUPPORTED;
10529 }
10530
10531 /****************************************************************
10532  _spoolss_SpoolerInit
10533 ****************************************************************/
10534
10535 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10536                             struct spoolss_SpoolerInit *r)
10537 {
10538         p->rng_fault_state = true;
10539         return WERR_NOT_SUPPORTED;
10540 }
10541
10542 /****************************************************************
10543  _spoolss_ResetPrinterEx
10544 ****************************************************************/
10545
10546 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10547                                struct spoolss_ResetPrinterEx *r)
10548 {
10549         p->rng_fault_state = true;
10550         return WERR_NOT_SUPPORTED;
10551 }
10552
10553 /****************************************************************
10554  _spoolss_RouterReplyPrinterEx
10555 ****************************************************************/
10556
10557 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10558                                      struct spoolss_RouterReplyPrinterEx *r)
10559 {
10560         p->rng_fault_state = true;
10561         return WERR_NOT_SUPPORTED;
10562 }
10563
10564 /****************************************************************
10565  _spoolss_44
10566 ****************************************************************/
10567
10568 WERROR _spoolss_44(struct pipes_struct *p,
10569                    struct spoolss_44 *r)
10570 {
10571         p->rng_fault_state = true;
10572         return WERR_NOT_SUPPORTED;
10573 }
10574
10575 /****************************************************************
10576  _spoolss_SetPort
10577 ****************************************************************/
10578
10579 WERROR _spoolss_SetPort(struct pipes_struct *p,
10580                         struct spoolss_SetPort *r)
10581 {
10582         p->rng_fault_state = true;
10583         return WERR_NOT_SUPPORTED;
10584 }
10585
10586 /****************************************************************
10587  _spoolss_4a
10588 ****************************************************************/
10589
10590 WERROR _spoolss_4a(struct pipes_struct *p,
10591                    struct spoolss_4a *r)
10592 {
10593         p->rng_fault_state = true;
10594         return WERR_NOT_SUPPORTED;
10595 }
10596
10597 /****************************************************************
10598  _spoolss_4b
10599 ****************************************************************/
10600
10601 WERROR _spoolss_4b(struct pipes_struct *p,
10602                    struct spoolss_4b *r)
10603 {
10604         p->rng_fault_state = true;
10605         return WERR_NOT_SUPPORTED;
10606 }
10607
10608 /****************************************************************
10609  _spoolss_4c
10610 ****************************************************************/
10611
10612 WERROR _spoolss_4c(struct pipes_struct *p,
10613                    struct spoolss_4c *r)
10614 {
10615         p->rng_fault_state = true;
10616         return WERR_NOT_SUPPORTED;
10617 }
10618
10619 /****************************************************************
10620  _spoolss_53
10621 ****************************************************************/
10622
10623 WERROR _spoolss_53(struct pipes_struct *p,
10624                    struct spoolss_53 *r)
10625 {
10626         p->rng_fault_state = true;
10627         return WERR_NOT_SUPPORTED;
10628 }
10629
10630 /****************************************************************
10631  _spoolss_AddPerMachineConnection
10632 ****************************************************************/
10633
10634 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10635                                         struct spoolss_AddPerMachineConnection *r)
10636 {
10637         p->rng_fault_state = true;
10638         return WERR_NOT_SUPPORTED;
10639 }
10640
10641 /****************************************************************
10642  _spoolss_DeletePerMachineConnection
10643 ****************************************************************/
10644
10645 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10646                                            struct spoolss_DeletePerMachineConnection *r)
10647 {
10648         p->rng_fault_state = true;
10649         return WERR_NOT_SUPPORTED;
10650 }
10651
10652 /****************************************************************
10653  _spoolss_EnumPerMachineConnections
10654 ****************************************************************/
10655
10656 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10657                                           struct spoolss_EnumPerMachineConnections *r)
10658 {
10659         p->rng_fault_state = true;
10660         return WERR_NOT_SUPPORTED;
10661 }
10662
10663 /****************************************************************
10664  _spoolss_5a
10665 ****************************************************************/
10666
10667 WERROR _spoolss_5a(struct pipes_struct *p,
10668                    struct spoolss_5a *r)
10669 {
10670         p->rng_fault_state = true;
10671         return WERR_NOT_SUPPORTED;
10672 }
10673
10674 /****************************************************************
10675  _spoolss_5b
10676 ****************************************************************/
10677
10678 WERROR _spoolss_5b(struct pipes_struct *p,
10679                    struct spoolss_5b *r)
10680 {
10681         p->rng_fault_state = true;
10682         return WERR_NOT_SUPPORTED;
10683 }
10684
10685 /****************************************************************
10686  _spoolss_5c
10687 ****************************************************************/
10688
10689 WERROR _spoolss_5c(struct pipes_struct *p,
10690                    struct spoolss_5c *r)
10691 {
10692         p->rng_fault_state = true;
10693         return WERR_NOT_SUPPORTED;
10694 }
10695
10696 /****************************************************************
10697  _spoolss_5d
10698 ****************************************************************/
10699
10700 WERROR _spoolss_5d(struct pipes_struct *p,
10701                    struct spoolss_5d *r)
10702 {
10703         p->rng_fault_state = true;
10704         return WERR_NOT_SUPPORTED;
10705 }
10706
10707 /****************************************************************
10708  _spoolss_5e
10709 ****************************************************************/
10710
10711 WERROR _spoolss_5e(struct pipes_struct *p,
10712                    struct spoolss_5e *r)
10713 {
10714         p->rng_fault_state = true;
10715         return WERR_NOT_SUPPORTED;
10716 }
10717
10718 /****************************************************************
10719  _spoolss_5f
10720 ****************************************************************/
10721
10722 WERROR _spoolss_5f(struct pipes_struct *p,
10723                    struct spoolss_5f *r)
10724 {
10725         p->rng_fault_state = true;
10726         return WERR_NOT_SUPPORTED;
10727 }
10728
10729 /****************************************************************
10730  _spoolss_60
10731 ****************************************************************/
10732
10733 WERROR _spoolss_60(struct pipes_struct *p,
10734                    struct spoolss_60 *r)
10735 {
10736         p->rng_fault_state = true;
10737         return WERR_NOT_SUPPORTED;
10738 }
10739
10740 /****************************************************************
10741  _spoolss_61
10742 ****************************************************************/
10743
10744 WERROR _spoolss_61(struct pipes_struct *p,
10745                    struct spoolss_61 *r)
10746 {
10747         p->rng_fault_state = true;
10748         return WERR_NOT_SUPPORTED;
10749 }
10750
10751 /****************************************************************
10752  _spoolss_62
10753 ****************************************************************/
10754
10755 WERROR _spoolss_62(struct pipes_struct *p,
10756                    struct spoolss_62 *r)
10757 {
10758         p->rng_fault_state = true;
10759         return WERR_NOT_SUPPORTED;
10760 }
10761
10762 /****************************************************************
10763  _spoolss_63
10764 ****************************************************************/
10765
10766 WERROR _spoolss_63(struct pipes_struct *p,
10767                    struct spoolss_63 *r)
10768 {
10769         p->rng_fault_state = true;
10770         return WERR_NOT_SUPPORTED;
10771 }
10772
10773 /****************************************************************
10774  _spoolss_64
10775 ****************************************************************/
10776
10777 WERROR _spoolss_64(struct pipes_struct *p,
10778                    struct spoolss_64 *r)
10779 {
10780         p->rng_fault_state = true;
10781         return WERR_NOT_SUPPORTED;
10782 }
10783
10784 /****************************************************************
10785  _spoolss_65
10786 ****************************************************************/
10787
10788 WERROR _spoolss_65(struct pipes_struct *p,
10789                    struct spoolss_65 *r)
10790 {
10791         p->rng_fault_state = true;
10792         return WERR_NOT_SUPPORTED;
10793 }
10794
10795 /****************************************************************
10796  _spoolss_GetCorePrinterDrivers
10797 ****************************************************************/
10798
10799 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10800                                       struct spoolss_GetCorePrinterDrivers *r)
10801 {
10802         p->rng_fault_state = true;
10803         return WERR_NOT_SUPPORTED;
10804 }
10805
10806 /****************************************************************
10807  _spoolss_67
10808 ****************************************************************/
10809
10810 WERROR _spoolss_67(struct pipes_struct *p,
10811                    struct spoolss_67 *r)
10812 {
10813         p->rng_fault_state = true;
10814         return WERR_NOT_SUPPORTED;
10815 }
10816
10817 /****************************************************************
10818  _spoolss_GetPrinterDriverPackagePath
10819 ****************************************************************/
10820
10821 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10822                                             struct spoolss_GetPrinterDriverPackagePath *r)
10823 {
10824         p->rng_fault_state = true;
10825         return WERR_NOT_SUPPORTED;
10826 }
10827
10828 /****************************************************************
10829  _spoolss_69
10830 ****************************************************************/
10831
10832 WERROR _spoolss_69(struct pipes_struct *p,
10833                    struct spoolss_69 *r)
10834 {
10835         p->rng_fault_state = true;
10836         return WERR_NOT_SUPPORTED;
10837 }
10838
10839 /****************************************************************
10840  _spoolss_6a
10841 ****************************************************************/
10842
10843 WERROR _spoolss_6a(struct pipes_struct *p,
10844                    struct spoolss_6a *r)
10845 {
10846         p->rng_fault_state = true;
10847         return WERR_NOT_SUPPORTED;
10848 }
10849
10850 /****************************************************************
10851  _spoolss_6b
10852 ****************************************************************/
10853
10854 WERROR _spoolss_6b(struct pipes_struct *p,
10855                    struct spoolss_6b *r)
10856 {
10857         p->rng_fault_state = true;
10858         return WERR_NOT_SUPPORTED;
10859 }
10860
10861 /****************************************************************
10862  _spoolss_6c
10863 ****************************************************************/
10864
10865 WERROR _spoolss_6c(struct pipes_struct *p,
10866                    struct spoolss_6c *r)
10867 {
10868         p->rng_fault_state = true;
10869         return WERR_NOT_SUPPORTED;
10870 }
10871
10872 /****************************************************************
10873  _spoolss_6d
10874 ****************************************************************/
10875
10876 WERROR _spoolss_6d(struct pipes_struct *p,
10877                    struct spoolss_6d *r)
10878 {
10879         p->rng_fault_state = true;
10880         return WERR_NOT_SUPPORTED;
10881 }