ef203d8f545c0fb4452f39f5077a3f7b4d3cd325
[metze/samba/wip.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 "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.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(talloc_tos());
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         return WERR_OK;
421 }
422
423 /****************************************************************************
424  Delete a printer given a handle.
425 ****************************************************************************/
426
427 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
428 {
429         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
430         WERROR result;
431
432         if (!Printer) {
433                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
434                         OUR_HANDLE(hnd)));
435                 return WERR_BADFID;
436         }
437
438         /*
439          * It turns out that Windows allows delete printer on a handle
440          * opened by an admin user, then used on a pipe handle created
441          * by an anonymous user..... but they're working on security.... riiight !
442          * JRA.
443          */
444
445         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
446                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
447                 return WERR_ACCESS_DENIED;
448         }
449
450         /* this does not need a become root since the access check has been
451            done on the handle already */
452
453         result = winreg_delete_printer_key_internal(p->mem_ctx,
454                                            get_session_info_system(),
455                                            p->msg_ctx,
456                                            Printer->sharename,
457                                            "");
458         if (!W_ERROR_IS_OK(result)) {
459                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
460                 return WERR_BADFID;
461         }
462
463         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
464                                      Printer->sharename, p->msg_ctx);
465         if (!W_ERROR_IS_OK(result)) {
466                 return result;
467         }
468         prune_printername_cache();
469         return WERR_OK;
470 }
471
472 /****************************************************************************
473  Return the snum of a printer corresponding to an handle.
474 ****************************************************************************/
475
476 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
477                              int *number, struct share_params **params)
478 {
479         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
480
481         if (!Printer) {
482                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
483                         OUR_HANDLE(hnd)));
484                 return false;
485         }
486
487         switch (Printer->printer_type) {
488                 case SPLHND_PRINTER:
489                         DEBUG(4,("short name:%s\n", Printer->sharename));
490                         *number = print_queue_snum(Printer->sharename);
491                         return (*number != -1);
492                 case SPLHND_SERVER:
493                         return false;
494                 default:
495                         return false;
496         }
497 }
498
499 /****************************************************************************
500  Set printer handle type.
501  Check if it's \\server or \\server\printer
502 ****************************************************************************/
503
504 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
505 {
506         DEBUG(3,("Setting printer type=%s\n", handlename));
507
508         /* it's a print server */
509         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
510                 DEBUGADD(4,("Printer is a print server\n"));
511                 Printer->printer_type = SPLHND_SERVER;
512         }
513         /* it's a printer (set_printer_hnd_name() will handle port monitors */
514         else {
515                 DEBUGADD(4,("Printer is a printer\n"));
516                 Printer->printer_type = SPLHND_PRINTER;
517         }
518
519         return true;
520 }
521
522 static void prune_printername_cache_fn(const char *key, const char *value,
523                                        time_t timeout, void *private_data)
524 {
525         gencache_del(key);
526 }
527
528 static void prune_printername_cache(void)
529 {
530         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
531 }
532
533 /****************************************************************************
534  Set printer handle name..  Accept names like \\server, \\server\printer,
535  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
536  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
537  XcvDataPort() interface.
538 ****************************************************************************/
539
540 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
541                                    const struct auth_session_info *session_info,
542                                    struct messaging_context *msg_ctx,
543                                    struct printer_handle *Printer,
544                                    const char *handlename)
545 {
546         int snum;
547         int n_services=lp_numservices();
548         char *aprinter;
549         const char *printername;
550         const char *servername = NULL;
551         fstring sname;
552         bool found = false;
553         struct spoolss_PrinterInfo2 *info2 = NULL;
554         WERROR result;
555         char *p;
556
557         /*
558          * Hopefully nobody names his printers like this. Maybe \ or ,
559          * are illegal in printer names even?
560          */
561         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
562         char *cache_key;
563         char *tmp;
564
565         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
566                 (unsigned long)strlen(handlename)));
567
568         aprinter = discard_const_p(char, handlename);
569         if ( *handlename == '\\' ) {
570                 servername = canon_servername(handlename);
571                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
572                         *aprinter = '\0';
573                         aprinter++;
574                 }
575                 if (!is_myname_or_ipaddr(servername)) {
576                         return WERR_INVALID_PRINTER_NAME;
577                 }
578                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
579                 if (Printer->servername == NULL) {
580                         return WERR_NOMEM;
581                 }
582         }
583
584         if (Printer->printer_type == SPLHND_SERVER) {
585                 return WERR_OK;
586         }
587
588         if (Printer->printer_type != SPLHND_PRINTER) {
589                 return WERR_INVALID_HANDLE;
590         }
591
592         DEBUGADD(5, ("searching for [%s]\n", aprinter));
593
594         p = strchr(aprinter, ',');
595         if (p != NULL) {
596                 char *p2 = p;
597                 p++;
598                 if (*p == ' ') {
599                         p++;
600                 }
601                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
602                         *p2 = '\0';
603                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
604                         *p2 = '\0';
605                 }
606         }
607
608         if (p) {
609                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
610         }
611
612         /* check for the Port Monitor Interface */
613         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
614                 Printer->printer_type = SPLHND_PORTMON_TCP;
615                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
616                 found = true;
617         }
618         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
619                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
620                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
621                 found = true;
622         }
623
624         /*
625          * With hundreds of printers, the "for" loop iterating all
626          * shares can be quite expensive, as it is done on every
627          * OpenPrinter. The loop maps "aprinter" to "sname", the
628          * result of which we cache in gencache.
629          */
630
631         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
632                                     aprinter);
633         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
634
635                 found = (strcmp(tmp, printer_not_found) != 0);
636                 if (!found) {
637                         DEBUG(4, ("Printer %s not found\n", aprinter));
638                         SAFE_FREE(tmp);
639                         return WERR_INVALID_PRINTER_NAME;
640                 }
641                 fstrcpy(sname, tmp);
642                 SAFE_FREE(tmp);
643         }
644
645         /* Search all sharenames first as this is easier than pulling
646            the printer_info_2 off of disk. Don't use find_service() since
647            that calls out to map_username() */
648
649         /* do another loop to look for printernames */
650         for (snum = 0; !found && snum < n_services; snum++) {
651                 const char *printer = lp_const_servicename(snum);
652
653                 /* no point going on if this is not a printer */
654                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
655                         continue;
656                 }
657
658                 /* ignore [printers] share */
659                 if (strequal(printer, "printers")) {
660                         continue;
661                 }
662
663                 fstrcpy(sname, printer);
664                 if (strequal(aprinter, printer)) {
665                         found = true;
666                         break;
667                 }
668
669                 /* no point looking up the printer object if
670                    we aren't allowing printername != sharename */
671                 if (lp_force_printername(snum)) {
672                         continue;
673                 }
674
675                 result = winreg_get_printer_internal(mem_ctx,
676                                             session_info,
677                                             msg_ctx,
678                                             sname,
679                                             &info2);
680                 if ( !W_ERROR_IS_OK(result) ) {
681                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
682                                  sname, win_errstr(result)));
683                         continue;
684                 }
685
686                 printername = strrchr(info2->printername, '\\');
687                 if (printername == NULL) {
688                         printername = info2->printername;
689                 } else {
690                         printername++;
691                 }
692
693                 if (strequal(printername, aprinter)) {
694                         found = true;
695                         break;
696                 }
697
698                 DEBUGADD(10, ("printername: %s\n", printername));
699
700                 TALLOC_FREE(info2);
701         }
702
703         if ( !found ) {
704                 if (cache_key != NULL) {
705                         gencache_set(cache_key, printer_not_found,
706                                      time(NULL)+300);
707                         TALLOC_FREE(cache_key);
708                 }
709                 DEBUGADD(4,("Printer not found\n"));
710                 return WERR_INVALID_PRINTER_NAME;
711         }
712
713         if (cache_key != NULL) {
714                 gencache_set(cache_key, sname, time(NULL)+300);
715                 TALLOC_FREE(cache_key);
716         }
717
718         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
719
720         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
721
722         return WERR_OK;
723 }
724
725 /****************************************************************************
726  Find first available printer slot. creates a printer handle for you.
727  ****************************************************************************/
728
729 static WERROR open_printer_hnd(struct pipes_struct *p,
730                                struct policy_handle *hnd,
731                                const char *name,
732                                uint32_t access_granted)
733 {
734         struct printer_handle *new_printer;
735         WERROR result;
736
737         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
738
739         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
740         if (new_printer == NULL) {
741                 return WERR_NOMEM;
742         }
743         talloc_set_destructor(new_printer, printer_entry_destructor);
744
745         /* This also steals the printer_handle on the policy_handle */
746         if (!create_policy_hnd(p, hnd, new_printer)) {
747                 TALLOC_FREE(new_printer);
748                 return WERR_INVALID_HANDLE;
749         }
750
751         /* Add to the internal list. */
752         DLIST_ADD(printers_list, new_printer);
753
754         new_printer->notify.option=NULL;
755
756         if (!set_printer_hnd_printertype(new_printer, name)) {
757                 close_printer_handle(p, hnd);
758                 return WERR_INVALID_HANDLE;
759         }
760
761         result = set_printer_hnd_name(p->mem_ctx,
762                                       get_session_info_system(),
763                                       p->msg_ctx,
764                                       new_printer, name);
765         if (!W_ERROR_IS_OK(result)) {
766                 close_printer_handle(p, hnd);
767                 return result;
768         }
769
770         new_printer->access_granted = access_granted;
771
772         DEBUG(5, ("%d printer handles active\n",
773                   (int)num_pipe_handles(p)));
774
775         return WERR_OK;
776 }
777
778 /***************************************************************************
779  check to see if the client motify handle is monitoring the notification
780  given by (notify_type, notify_field).
781  **************************************************************************/
782
783 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
784                                       uint16_t notify_field)
785 {
786         return true;
787 }
788
789 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
790                                 uint16_t notify_field)
791 {
792         struct spoolss_NotifyOption *option = p->notify.option;
793         uint32_t i, j;
794
795         /*
796          * Flags should always be zero when the change notify
797          * is registered by the client's spooler.  A user Win32 app
798          * might use the flags though instead of the NOTIFY_OPTION_INFO
799          * --jerry
800          */
801
802         if (!option) {
803                 return false;
804         }
805
806         if (p->notify.flags)
807                 return is_monitoring_event_flags(
808                         p->notify.flags, notify_type, notify_field);
809
810         for (i = 0; i < option->count; i++) {
811
812                 /* Check match for notify_type */
813
814                 if (option->types[i].type != notify_type)
815                         continue;
816
817                 /* Check match for field */
818
819                 for (j = 0; j < option->types[i].count; j++) {
820                         if (option->types[i].fields[j].field == notify_field) {
821                                 return true;
822                         }
823                 }
824         }
825
826         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
827                    p->servername, p->sharename, notify_type, notify_field));
828
829         return false;
830 }
831
832 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
833         _data->data.integer[0] = _integer; \
834         _data->data.integer[1] = 0;
835
836
837 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
838         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
839         if (!_data->data.string.string) {\
840                 _data->data.string.size = 0; \
841         } \
842         _data->data.string.size = strlen_m_term(_p) * 2;
843
844 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
845         _data->data.devmode.devmode = _devmode;
846
847 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
848         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
849         if (!_data->data.sd.sd) { \
850                 _data->data.sd.sd_size = 0; \
851         } \
852         _data->data.sd.sd_size = \
853                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
854
855 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
856                                    struct tm *t,
857                                    const char **pp,
858                                    uint32_t *plen)
859 {
860         struct spoolss_Time st;
861         uint32_t len = 16;
862         char *p;
863
864         if (!init_systemtime(&st, t)) {
865                 return;
866         }
867
868         p = talloc_array(mem_ctx, char, len);
869         if (!p) {
870                 return;
871         }
872
873         /*
874          * Systemtime must be linearized as a set of UINT16's.
875          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
876          */
877
878         SSVAL(p, 0, st.year);
879         SSVAL(p, 2, st.month);
880         SSVAL(p, 4, st.day_of_week);
881         SSVAL(p, 6, st.day);
882         SSVAL(p, 8, st.hour);
883         SSVAL(p, 10, st.minute);
884         SSVAL(p, 12, st.second);
885         SSVAL(p, 14, st.millisecond);
886
887         *pp = p;
888         *plen = len;
889 }
890
891 /* Convert a notification message to a struct spoolss_Notify */
892
893 static void notify_one_value(struct spoolss_notify_msg *msg,
894                              struct spoolss_Notify *data,
895                              TALLOC_CTX *mem_ctx)
896 {
897         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
898 }
899
900 static void notify_string(struct spoolss_notify_msg *msg,
901                           struct spoolss_Notify *data,
902                           TALLOC_CTX *mem_ctx)
903 {
904         /* The length of the message includes the trailing \0 */
905
906         data->data.string.size = msg->len * 2;
907         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
908         if (!data->data.string.string) {
909                 data->data.string.size = 0;
910                 return;
911         }
912 }
913
914 static void notify_system_time(struct spoolss_notify_msg *msg,
915                                struct spoolss_Notify *data,
916                                TALLOC_CTX *mem_ctx)
917 {
918         data->data.string.string = NULL;
919         data->data.string.size = 0;
920
921         if (msg->len != sizeof(time_t)) {
922                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
923                           msg->len));
924                 return;
925         }
926
927         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
928                                &data->data.string.string,
929                                &data->data.string.size);
930 }
931
932 struct notify2_message_table {
933         const char *name;
934         void (*fn)(struct spoolss_notify_msg *msg,
935                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
936 };
937
938 static struct notify2_message_table printer_notify_table[] = {
939         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
940         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
941         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
942         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
943         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
944         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
945         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
946         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
947         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
948         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
949         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
950         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
951         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
952         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
953         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
954         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
955         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
956         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
957         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
958 };
959
960 static struct notify2_message_table job_notify_table[] = {
961         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
962         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
963         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
964         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
965         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
966         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
967         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
968         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
969         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
970         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
971         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
972         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
973         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
974         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
975         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
976         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
977         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
978         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
979         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
980         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
981         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
982         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
983         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
984         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
985 };
986
987
988 /***********************************************************************
989  Allocate talloc context for container object
990  **********************************************************************/
991
992 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
993 {
994         if ( !ctr )
995                 return;
996
997         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
998
999         return;
1000 }
1001
1002 /***********************************************************************
1003  release all allocated memory and zero out structure
1004  **********************************************************************/
1005
1006 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1007 {
1008         if ( !ctr )
1009                 return;
1010
1011         if ( ctr->ctx )
1012                 talloc_destroy(ctr->ctx);
1013
1014         ZERO_STRUCTP(ctr);
1015
1016         return;
1017 }
1018
1019 /***********************************************************************
1020  **********************************************************************/
1021
1022 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1023 {
1024         if ( !ctr )
1025                 return NULL;
1026
1027         return ctr->ctx;
1028 }
1029
1030 /***********************************************************************
1031  **********************************************************************/
1032
1033 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1034 {
1035         if ( !ctr || !ctr->msg_groups )
1036                 return NULL;
1037
1038         if ( idx >= ctr->num_groups )
1039                 return NULL;
1040
1041         return &ctr->msg_groups[idx];
1042
1043 }
1044
1045 /***********************************************************************
1046  How many groups of change messages do we have ?
1047  **********************************************************************/
1048
1049 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1050 {
1051         if ( !ctr )
1052                 return 0;
1053
1054         return ctr->num_groups;
1055 }
1056
1057 /***********************************************************************
1058  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1059  **********************************************************************/
1060
1061 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1062 {
1063         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1064         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1065         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1066         int                             i, new_slot;
1067
1068         if ( !ctr || !msg )
1069                 return 0;
1070
1071         /* loop over all groups looking for a matching printer name */
1072
1073         for ( i=0; i<ctr->num_groups; i++ ) {
1074                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1075                         break;
1076         }
1077
1078         /* add a new group? */
1079
1080         if ( i == ctr->num_groups ) {
1081                 ctr->num_groups++;
1082
1083                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1084                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1085                         return 0;
1086                 }
1087                 ctr->msg_groups = groups;
1088
1089                 /* clear the new entry and set the printer name */
1090
1091                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1092                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1093         }
1094
1095         /* add the change messages; 'i' is the correct index now regardless */
1096
1097         msg_grp = &ctr->msg_groups[i];
1098
1099         msg_grp->num_msgs++;
1100
1101         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1102                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1103                 return 0;
1104         }
1105         msg_grp->msgs = msg_list;
1106
1107         new_slot = msg_grp->num_msgs-1;
1108         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1109
1110         /* need to allocate own copy of data */
1111
1112         if ( msg->len != 0 )
1113                 msg_grp->msgs[new_slot].notify.data = (char *)
1114                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1115
1116         return ctr->num_groups;
1117 }
1118
1119 static void construct_info_data(struct spoolss_Notify *info_data,
1120                                 enum spoolss_NotifyType type,
1121                                 uint16_t field, int id);
1122
1123 /***********************************************************************
1124  Send a change notication message on all handles which have a call
1125  back registered
1126  **********************************************************************/
1127
1128 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1129                                   struct printer_handle *prn_hnd,
1130                                   SPOOLSS_NOTIFY_MSG *messages,
1131                                   uint32_t num_msgs,
1132                                   struct spoolss_Notify **_notifies,
1133                                   int *_count)
1134 {
1135         struct spoolss_Notify *notifies;
1136         SPOOLSS_NOTIFY_MSG *msg;
1137         int count = 0;
1138         uint32_t id;
1139         int i;
1140
1141         notifies = talloc_zero_array(mem_ctx,
1142                                      struct spoolss_Notify, num_msgs);
1143         if (!notifies) {
1144                 return ENOMEM;
1145         }
1146
1147         for (i = 0; i < num_msgs; i++) {
1148
1149                 msg = &messages[i];
1150
1151                 /* Are we monitoring this event? */
1152
1153                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1154                         continue;
1155                 }
1156
1157                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1158                            "for printer [%s]\n",
1159                            msg->type, msg->field, prn_hnd->sharename));
1160
1161                 /*
1162                  * if the is a printer notification handle and not a job
1163                  * notification type, then set the id to 0.
1164                  * Otherwise just use what was specified in the message.
1165                  *
1166                  * When registering change notification on a print server
1167                  * handle we always need to send back the id (snum) matching
1168                  * the printer for which the change took place.
1169                  * For change notify registered on a printer handle,
1170                  * this does not matter and the id should be 0.
1171                  *
1172                  * --jerry
1173                  */
1174
1175                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1176                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1177                         id = 0;
1178                 } else {
1179                         id = msg->id;
1180                 }
1181
1182                 /* Convert unix jobid to smb jobid */
1183
1184                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1185                         id = sysjob_to_jobid(msg->id);
1186
1187                         if (id == -1) {
1188                                 DEBUG(3, ("no such unix jobid %d\n",
1189                                           msg->id));
1190                                 continue;
1191                         }
1192                 }
1193
1194                 construct_info_data(&notifies[count],
1195                                     msg->type, msg->field, id);
1196
1197                 switch(msg->type) {
1198                 case PRINTER_NOTIFY_TYPE:
1199                         if (printer_notify_table[msg->field].fn) {
1200                                 printer_notify_table[msg->field].fn(msg,
1201                                                 &notifies[count], mem_ctx);
1202                         }
1203                         break;
1204
1205                 case JOB_NOTIFY_TYPE:
1206                         if (job_notify_table[msg->field].fn) {
1207                                 job_notify_table[msg->field].fn(msg,
1208                                                 &notifies[count], mem_ctx);
1209                         }
1210                         break;
1211
1212                 default:
1213                         DEBUG(5, ("Unknown notification type %d\n",
1214                                   msg->type));
1215                         continue;
1216                 }
1217
1218                 count++;
1219         }
1220
1221         *_notifies = notifies;
1222         *_count = count;
1223
1224         return 0;
1225 }
1226
1227 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1228                                 struct printer_handle *prn_hnd,
1229                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1230 {
1231         struct spoolss_Notify *notifies;
1232         int count = 0;
1233         union spoolss_ReplyPrinterInfo info;
1234         struct spoolss_NotifyInfo info0;
1235         uint32_t reply_result;
1236         NTSTATUS status;
1237         WERROR werr;
1238         int ret;
1239
1240         /* Is there notification on this handle? */
1241         if (prn_hnd->notify.cli_chan == NULL ||
1242             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1243             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1244             prn_hnd->notify.cli_chan->active_connections == 0) {
1245                 return 0;
1246         }
1247
1248         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1249                    prn_hnd->servername, prn_hnd->sharename));
1250
1251         /* For this printer? Print servers always receive notifications. */
1252         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1253             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1254                 return 0;
1255         }
1256
1257         DEBUG(10,("Our printer\n"));
1258
1259         /* build the array of change notifications */
1260         ret = build_notify2_messages(mem_ctx, prn_hnd,
1261                                      msg_group->msgs,
1262                                      msg_group->num_msgs,
1263                                      &notifies, &count);
1264         if (ret) {
1265                 return ret;
1266         }
1267
1268         info0.version   = 0x2;
1269         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1270         info0.count     = count;
1271         info0.notifies  = notifies;
1272
1273         info.info0 = &info0;
1274
1275         status = dcerpc_spoolss_RouterReplyPrinterEx(
1276                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1277                                 mem_ctx,
1278                                 &prn_hnd->notify.cli_hnd,
1279                                 prn_hnd->notify.change, /* color */
1280                                 prn_hnd->notify.flags,
1281                                 &reply_result,
1282                                 0, /* reply_type, must be 0 */
1283                                 info, &werr);
1284         if (!NT_STATUS_IS_OK(status)) {
1285                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1286                           "failed: %s\n",
1287                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1288                           nt_errstr(status)));
1289                 werr = ntstatus_to_werror(status);
1290         } else if (!W_ERROR_IS_OK(werr)) {
1291                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1292                           "failed: %s\n",
1293                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1294                           win_errstr(werr)));
1295         }
1296         switch (reply_result) {
1297         case 0:
1298                 break;
1299         case PRINTER_NOTIFY_INFO_DISCARDED:
1300         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1301         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1302                 break;
1303         default:
1304                 break;
1305         }
1306
1307         return 0;
1308 }
1309
1310 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1311 {
1312         struct printer_handle    *p;
1313         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1314         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1315         int ret;
1316
1317         if ( !msg_group ) {
1318                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1319                 return;
1320         }
1321
1322         if (!msg_group->msgs) {
1323                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1324                 return;
1325         }
1326
1327         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1328
1329         /* loop over all printers */
1330
1331         for (p = printers_list; p; p = p->next) {
1332                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1333                 if (ret) {
1334                         goto done;
1335                 }
1336         }
1337
1338 done:
1339         DEBUG(8,("send_notify2_changes: Exit...\n"));
1340         return;
1341 }
1342
1343 /***********************************************************************
1344  **********************************************************************/
1345
1346 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1347 {
1348
1349         uint32_t tv_sec, tv_usec;
1350         size_t offset = 0;
1351
1352         /* Unpack message */
1353
1354         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1355                              msg->printer);
1356
1357         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1358                                 &tv_sec, &tv_usec,
1359                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1360
1361         if (msg->len == 0)
1362                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1363                            &msg->notify.value[0], &msg->notify.value[1]);
1364         else
1365                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1366                            &msg->len, &msg->notify.data);
1367
1368         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1369                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1370
1371         tv->tv_sec = tv_sec;
1372         tv->tv_usec = tv_usec;
1373
1374         if (msg->len == 0)
1375                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1376                           msg->notify.value[1]));
1377         else
1378                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1379
1380         return true;
1381 }
1382
1383 /********************************************************************
1384  Receive a notify2 message list
1385  ********************************************************************/
1386
1387 static void receive_notify2_message_list(struct messaging_context *msg,
1388                                          void *private_data,
1389                                          uint32_t msg_type,
1390                                          struct server_id server_id,
1391                                          DATA_BLOB *data)
1392 {
1393         size_t                  msg_count, i;
1394         char                    *buf = (char *)data->data;
1395         char                    *msg_ptr;
1396         size_t                  msg_len;
1397         SPOOLSS_NOTIFY_MSG      notify;
1398         SPOOLSS_NOTIFY_MSG_CTR  messages;
1399         int                     num_groups;
1400
1401         if (data->length < 4) {
1402                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1403                 return;
1404         }
1405
1406         msg_count = IVAL(buf, 0);
1407         msg_ptr = buf + 4;
1408
1409         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1410
1411         if (msg_count == 0) {
1412                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1413                 return;
1414         }
1415
1416         /* initialize the container */
1417
1418         ZERO_STRUCT( messages );
1419         notify_msg_ctr_init( &messages );
1420
1421         /*
1422          * build message groups for each printer identified
1423          * in a change_notify msg.  Remember that a PCN message
1424          * includes the handle returned for the srv_spoolss_replyopenprinter()
1425          * call.  Therefore messages are grouped according to printer handle.
1426          */
1427
1428         for ( i=0; i<msg_count; i++ ) {
1429                 struct timeval msg_tv;
1430
1431                 if (msg_ptr + 4 - buf > data->length) {
1432                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1433                         return;
1434                 }
1435
1436                 msg_len = IVAL(msg_ptr,0);
1437                 msg_ptr += 4;
1438
1439                 if (msg_ptr + msg_len - buf > data->length) {
1440                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1441                         return;
1442                 }
1443
1444                 /* unpack messages */
1445
1446                 ZERO_STRUCT( notify );
1447                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1448                 msg_ptr += msg_len;
1449
1450                 /* add to correct list in container */
1451
1452                 notify_msg_ctr_addmsg( &messages, &notify );
1453
1454                 /* free memory that might have been allocated by notify2_unpack_msg() */
1455
1456                 if ( notify.len != 0 )
1457                         SAFE_FREE( notify.notify.data );
1458         }
1459
1460         /* process each group of messages */
1461
1462         num_groups = notify_msg_ctr_numgroups( &messages );
1463         for ( i=0; i<num_groups; i++ )
1464                 send_notify2_changes( &messages, i );
1465
1466
1467         /* cleanup */
1468
1469         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1470                 (uint32_t)msg_count ));
1471
1472         notify_msg_ctr_destroy( &messages );
1473
1474         return;
1475 }
1476
1477 /********************************************************************
1478  Send a message to ourself about new driver being installed
1479  so we can upgrade the information for each printer bound to this
1480  driver
1481  ********************************************************************/
1482
1483 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1484                                             struct messaging_context *msg_ctx)
1485 {
1486         int len = strlen(drivername);
1487
1488         if (!len)
1489                 return false;
1490
1491         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1492                 drivername));
1493
1494         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1495                            MSG_PRINTER_DRVUPGRADE,
1496                            (const uint8_t *)drivername, len+1);
1497
1498         return true;
1499 }
1500
1501 void srv_spoolss_cleanup(void)
1502 {
1503         struct printer_session_counter *session_counter;
1504
1505         for (session_counter = counter_list;
1506              session_counter != NULL;
1507              session_counter = counter_list) {
1508                 DLIST_REMOVE(counter_list, session_counter);
1509                 TALLOC_FREE(session_counter);
1510         }
1511 }
1512
1513 /**********************************************************************
1514  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1515  over all printers, upgrading ones as necessary
1516  **********************************************************************/
1517
1518 void do_drv_upgrade_printer(struct messaging_context *msg,
1519                             void *private_data,
1520                             uint32_t msg_type,
1521                             struct server_id server_id,
1522                             DATA_BLOB *data)
1523 {
1524         TALLOC_CTX *tmp_ctx;
1525         const struct auth_session_info *session_info = get_session_info_system();
1526         struct spoolss_PrinterInfo2 *pinfo2;
1527         WERROR result;
1528         const char *drivername;
1529         int snum;
1530         int n_services = lp_numservices();
1531         struct dcerpc_binding_handle *b = NULL;
1532
1533         tmp_ctx = talloc_new(NULL);
1534         if (!tmp_ctx) return;
1535
1536         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1537         if (!drivername) {
1538                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1539                 goto done;
1540         }
1541
1542         DEBUG(10, ("do_drv_upgrade_printer: "
1543                    "Got message for new driver [%s]\n", drivername));
1544
1545         /* Iterate the printer list */
1546
1547         for (snum = 0; snum < n_services; snum++) {
1548                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1549                         continue;
1550                 }
1551
1552                 /* ignore [printers] share */
1553                 if (strequal(lp_const_servicename(snum), "printers")) {
1554                         continue;
1555                 }
1556
1557                 if (b == NULL) {
1558                         result = winreg_printer_binding_handle(tmp_ctx,
1559                                                                session_info,
1560                                                                msg,
1561                                                                &b);
1562                         if (!W_ERROR_IS_OK(result)) {
1563                                 break;
1564                         }
1565                 }
1566
1567                 result = winreg_get_printer(tmp_ctx, b,
1568                                             lp_const_servicename(snum),
1569                                             &pinfo2);
1570
1571                 if (!W_ERROR_IS_OK(result)) {
1572                         continue;
1573                 }
1574
1575                 if (!pinfo2->drivername) {
1576                         continue;
1577                 }
1578
1579                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1580                         continue;
1581                 }
1582
1583                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1584
1585                 /* all we care about currently is the change_id */
1586                 result = winreg_printer_update_changeid(tmp_ctx, b,
1587                                                         pinfo2->printername);
1588
1589                 if (!W_ERROR_IS_OK(result)) {
1590                         DEBUG(3, ("do_drv_upgrade_printer: "
1591                                   "Failed to update changeid [%s]\n",
1592                                   win_errstr(result)));
1593                 }
1594         }
1595
1596         /* all done */
1597 done:
1598         talloc_free(tmp_ctx);
1599 }
1600
1601 /********************************************************************
1602  Update the cache for all printq's with a registered client
1603  connection
1604  ********************************************************************/
1605
1606 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1607 {
1608         struct printer_handle *printer = printers_list;
1609         int snum;
1610
1611         /* loop through all printers and update the cache where
1612            a client is connected */
1613         while (printer) {
1614                 if ((printer->printer_type == SPLHND_PRINTER) &&
1615                     ((printer->notify.cli_chan != NULL) &&
1616                      (printer->notify.cli_chan->active_connections > 0))) {
1617                         snum = print_queue_snum(printer->sharename);
1618                         print_queue_status(msg_ctx, snum, NULL, NULL);
1619                 }
1620
1621                 printer = printer->next;
1622         }
1623
1624         return;
1625 }
1626
1627 /****************************************************************
1628  _spoolss_OpenPrinter
1629 ****************************************************************/
1630
1631 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1632                             struct spoolss_OpenPrinter *r)
1633 {
1634         struct spoolss_OpenPrinterEx e;
1635         struct spoolss_UserLevel1 level1;
1636         WERROR werr;
1637
1638         ZERO_STRUCT(level1);
1639
1640         e.in.printername        = r->in.printername;
1641         e.in.datatype           = r->in.datatype;
1642         e.in.devmode_ctr        = r->in.devmode_ctr;
1643         e.in.access_mask        = r->in.access_mask;
1644         e.in.userlevel_ctr.level                = 1;
1645         e.in.userlevel_ctr.user_info.level1     = &level1;
1646
1647         e.out.handle            = r->out.handle;
1648
1649         werr = _spoolss_OpenPrinterEx(p, &e);
1650
1651         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1652                 /* OpenPrinterEx returns this for a bad
1653                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1654                  * instead.
1655                  */
1656                 werr = WERR_INVALID_PRINTER_NAME;
1657         }
1658
1659         return werr;
1660 }
1661
1662 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1663                               struct spoolss_DeviceMode *orig,
1664                               struct spoolss_DeviceMode **dest)
1665 {
1666         struct spoolss_DeviceMode *dm;
1667
1668         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1669         if (!dm) {
1670                 return WERR_NOMEM;
1671         }
1672
1673         /* copy all values, then duplicate strings and structs */
1674         *dm = *orig;
1675
1676         dm->devicename = talloc_strdup(dm, orig->devicename);
1677         if (!dm->devicename) {
1678                 return WERR_NOMEM;
1679         }
1680         dm->formname = talloc_strdup(dm, orig->formname);
1681         if (!dm->formname) {
1682                 return WERR_NOMEM;
1683         }
1684         if (orig->driverextra_data.data) {
1685                 dm->driverextra_data.data =
1686                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1687                                         orig->driverextra_data.length);
1688                 if (!dm->driverextra_data.data) {
1689                         return WERR_NOMEM;
1690                 }
1691         }
1692
1693         *dest = dm;
1694         return WERR_OK;
1695 }
1696
1697 /****************************************************************
1698  _spoolss_OpenPrinterEx
1699 ****************************************************************/
1700
1701 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1702                               struct spoolss_OpenPrinterEx *r)
1703 {
1704         int snum;
1705         char *raddr;
1706         char *rhost;
1707         struct printer_handle *Printer=NULL;
1708         WERROR result;
1709         int rc;
1710
1711         if (!r->in.printername) {
1712                 return WERR_INVALID_PARAM;
1713         }
1714
1715         if (!*r->in.printername) {
1716                 return WERR_INVALID_PARAM;
1717         }
1718
1719         if (r->in.userlevel_ctr.level > 3) {
1720                 return WERR_INVALID_PARAM;
1721         }
1722         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1723             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1724             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1725                 return WERR_INVALID_PARAM;
1726         }
1727
1728         /* some sanity check because you can open a printer or a print server */
1729         /* aka: \\server\printer or \\server */
1730
1731         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1732
1733         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1734         if (!W_ERROR_IS_OK(result)) {
1735                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1736                         "for printer %s\n", r->in.printername));
1737                 ZERO_STRUCTP(r->out.handle);
1738                 return result;
1739         }
1740
1741         Printer = find_printer_index_by_hnd(p, r->out.handle);
1742         if ( !Printer ) {
1743                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1744                         "handle we created for printer %s\n", r->in.printername));
1745                 close_printer_handle(p, r->out.handle);
1746                 ZERO_STRUCTP(r->out.handle);
1747                 return WERR_INVALID_PARAM;
1748         }
1749
1750         /*
1751          * First case: the user is opening the print server:
1752          *
1753          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1754          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1755          *
1756          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1757          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1758          * or if the user is listed in the smb.conf printer admin parameter.
1759          *
1760          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1761          * client view printer folder, but does not show the MSAPW.
1762          *
1763          * Note: this test needs code to check access rights here too. Jeremy
1764          * could you look at this?
1765          *
1766          * Second case: the user is opening a printer:
1767          * NT doesn't let us connect to a printer if the connecting user
1768          * doesn't have print permission.
1769          *
1770          * Third case: user is opening a Port Monitor
1771          * access checks same as opening a handle to the print server.
1772          */
1773
1774         switch (Printer->printer_type )
1775         {
1776         case SPLHND_SERVER:
1777         case SPLHND_PORTMON_TCP:
1778         case SPLHND_PORTMON_LOCAL:
1779                 /* Printserver handles use global struct... */
1780
1781                 snum = -1;
1782
1783                 /* Map standard access rights to object specific access rights */
1784
1785                 se_map_standard(&r->in.access_mask,
1786                                 &printserver_std_mapping);
1787
1788                 /* Deny any object specific bits that don't apply to print
1789                    servers (i.e printer and job specific bits) */
1790
1791                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1792
1793                 if (r->in.access_mask &
1794                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1795                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1796                         close_printer_handle(p, r->out.handle);
1797                         ZERO_STRUCTP(r->out.handle);
1798                         return WERR_ACCESS_DENIED;
1799                 }
1800
1801                 /* Allow admin access */
1802
1803                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1804                 {
1805                         if (!lp_ms_add_printer_wizard()) {
1806                                 close_printer_handle(p, r->out.handle);
1807                                 ZERO_STRUCTP(r->out.handle);
1808                                 return WERR_ACCESS_DENIED;
1809                         }
1810
1811                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1812                            and not a printer admin, then fail */
1813
1814                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1815                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1816                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1817                                                 p->session_info->security_token)) {
1818                                 close_printer_handle(p, r->out.handle);
1819                                 ZERO_STRUCTP(r->out.handle);
1820                                 DEBUG(3,("access DENIED as user is not root, "
1821                                         "has no printoperator privilege, "
1822                                         "not a member of the printoperator builtin group and "
1823                                         "is not in printer admin list"));
1824                                 return WERR_ACCESS_DENIED;
1825                         }
1826
1827                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1828                 }
1829                 else
1830                 {
1831                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1832                 }
1833
1834                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1835                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1836
1837                 /* We fall through to return WERR_OK */
1838                 break;
1839
1840         case SPLHND_PRINTER:
1841                 /* NT doesn't let us connect to a printer if the connecting user
1842                    doesn't have print permission.  */
1843
1844                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1845                         close_printer_handle(p, r->out.handle);
1846                         ZERO_STRUCTP(r->out.handle);
1847                         return WERR_BADFID;
1848                 }
1849
1850                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1851                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1852                 }
1853
1854                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1855
1856                 /* map an empty access mask to the minimum access mask */
1857                 if (r->in.access_mask == 0x0)
1858                         r->in.access_mask = PRINTER_ACCESS_USE;
1859
1860                 /*
1861                  * If we are not serving the printer driver for this printer,
1862                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1863                  * will keep NT clients happy  --jerry
1864                  */
1865
1866                 if (lp_use_client_driver(snum)
1867                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1868                 {
1869                         r->in.access_mask = PRINTER_ACCESS_USE;
1870                 }
1871
1872                 /* check smb.conf parameters and the the sec_desc */
1873                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1874                                                          p->mem_ctx);
1875                 if (raddr == NULL) {
1876                         return WERR_NOMEM;
1877                 }
1878
1879                 rc = get_remote_hostname(p->remote_address,
1880                                          &rhost,
1881                                          p->mem_ctx);
1882                 if (rc < 0) {
1883                         return WERR_NOMEM;
1884                 }
1885                 if (strequal(rhost, "UNKNOWN")) {
1886                         rhost = raddr;
1887                 }
1888
1889                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1890                                   rhost, raddr)) {
1891                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1892                         ZERO_STRUCTP(r->out.handle);
1893                         return WERR_ACCESS_DENIED;
1894                 }
1895
1896                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1897                                    p->session_info->security_token, snum) ||
1898                     !print_access_check(p->session_info,
1899                                         p->msg_ctx,
1900                                         snum,
1901                                         r->in.access_mask)) {
1902                         DEBUG(3, ("access DENIED for printer open\n"));
1903                         close_printer_handle(p, r->out.handle);
1904                         ZERO_STRUCTP(r->out.handle);
1905                         return WERR_ACCESS_DENIED;
1906                 }
1907
1908                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1909                         DEBUG(3, ("access DENIED for printer open - unknown bits\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 & PRINTER_ACCESS_ADMINISTER)
1916                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1917                 else
1918                         r->in.access_mask = PRINTER_ACCESS_USE;
1919
1920                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1921                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1922
1923                 winreg_create_printer_internal(p->mem_ctx,
1924                                       get_session_info_system(),
1925                                       p->msg_ctx,
1926                                       lp_const_servicename(snum));
1927
1928                 break;
1929
1930         default:
1931                 /* sanity check to prevent programmer error */
1932                 ZERO_STRUCTP(r->out.handle);
1933                 return WERR_BADFID;
1934         }
1935
1936         Printer->access_granted = r->in.access_mask;
1937
1938         /*
1939          * If the client sent a devmode in the OpenPrinter() call, then
1940          * save it here in case we get a job submission on this handle
1941          */
1942
1943          if ((Printer->printer_type != SPLHND_SERVER)
1944           && (r->in.devmode_ctr.devmode != NULL)) {
1945                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1946                                 &Printer->devmode);
1947          }
1948
1949         return WERR_OK;
1950 }
1951
1952 /****************************************************************
1953  _spoolss_ClosePrinter
1954 ****************************************************************/
1955
1956 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1957                              struct spoolss_ClosePrinter *r)
1958 {
1959         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1960
1961         if (Printer && Printer->document_started) {
1962                 struct spoolss_EndDocPrinter e;
1963
1964                 e.in.handle = r->in.handle;
1965
1966                 _spoolss_EndDocPrinter(p, &e);
1967         }
1968
1969         if (!close_printer_handle(p, r->in.handle))
1970                 return WERR_BADFID;
1971
1972         /* clear the returned printer handle.  Observed behavior
1973            from Win2k server.  Don't think this really matters.
1974            Previous code just copied the value of the closed
1975            handle.    --jerry */
1976
1977         ZERO_STRUCTP(r->out.handle);
1978
1979         return WERR_OK;
1980 }
1981
1982 /****************************************************************
1983  _spoolss_DeletePrinter
1984 ****************************************************************/
1985
1986 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1987                               struct spoolss_DeletePrinter *r)
1988 {
1989         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1990         WERROR result;
1991         int snum;
1992
1993         if (Printer && Printer->document_started) {
1994                 struct spoolss_EndDocPrinter e;
1995
1996                 e.in.handle = r->in.handle;
1997
1998                 _spoolss_EndDocPrinter(p, &e);
1999         }
2000
2001         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2002                 winreg_delete_printer_key_internal(p->mem_ctx,
2003                                           get_session_info_system(),
2004                                           p->msg_ctx,
2005                                           lp_const_servicename(snum),
2006                                           "");
2007         }
2008
2009         result = delete_printer_handle(p, r->in.handle);
2010
2011         return result;
2012 }
2013
2014 /*******************************************************************
2015  * static function to lookup the version id corresponding to an
2016  * long architecture string
2017  ******************************************************************/
2018
2019 static const struct print_architecture_table_node archi_table[]= {
2020
2021         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2022         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2023         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2024         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2025         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2026         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2027         {"Windows x64",          SPL_ARCH_X64,          3 },
2028         {NULL,                   "",            -1 }
2029 };
2030
2031 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2032                                    SPOOLSS_DRIVER_VERSION_NT35,
2033                                    SPOOLSS_DRIVER_VERSION_NT4,
2034                                    SPOOLSS_DRIVER_VERSION_200X,
2035                                    -1};
2036
2037 static int get_version_id(const char *arch)
2038 {
2039         int i;
2040
2041         for (i=0; archi_table[i].long_archi != NULL; i++)
2042         {
2043                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2044                         return (archi_table[i].version);
2045         }
2046
2047         return -1;
2048 }
2049
2050 /****************************************************************
2051  _spoolss_DeletePrinterDriver
2052 ****************************************************************/
2053
2054 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2055                                     struct spoolss_DeletePrinterDriver *r)
2056 {
2057
2058         struct spoolss_DriverInfo8 *info = NULL;
2059         int                             version;
2060         WERROR                          status;
2061         struct dcerpc_binding_handle *b;
2062         TALLOC_CTX *tmp_ctx = NULL;
2063         int i;
2064         bool found;
2065
2066         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2067            and not a printer admin, then fail */
2068
2069         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2070             !security_token_has_privilege(p->session_info->security_token,
2071                                           SEC_PRIV_PRINT_OPERATOR)) {
2072                 return WERR_ACCESS_DENIED;
2073         }
2074
2075         /* check that we have a valid driver name first */
2076
2077         if ((version = get_version_id(r->in.architecture)) == -1) {
2078                 return WERR_INVALID_ENVIRONMENT;
2079         }
2080
2081         tmp_ctx = talloc_new(p->mem_ctx);
2082         if (!tmp_ctx) {
2083                 return WERR_NOMEM;
2084         }
2085
2086         status = winreg_printer_binding_handle(tmp_ctx,
2087                                                get_session_info_system(),
2088                                                p->msg_ctx,
2089                                                &b);
2090         if (!W_ERROR_IS_OK(status)) {
2091                 goto done;
2092         }
2093
2094         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2095                 status = winreg_get_driver(tmp_ctx, b,
2096                                            r->in.architecture, r->in.driver,
2097                                            drv_cversion[i], &info);
2098                 if (!W_ERROR_IS_OK(status)) {
2099                         DEBUG(5, ("skipping del of driver with version %d\n",
2100                                   drv_cversion[i]));
2101                         continue;
2102                 }
2103                 found = true;
2104
2105                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2106                         status = WERR_PRINTER_DRIVER_IN_USE;
2107                         goto done;
2108                 }
2109
2110                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2111                 if (!W_ERROR_IS_OK(status)) {
2112                         DEBUG(0, ("failed del of driver with version %d\n",
2113                                   drv_cversion[i]));
2114                         goto done;
2115                 }
2116         }
2117         if (found == false) {
2118                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2119                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2120         } else {
2121                 status = WERR_OK;
2122         }
2123
2124 done:
2125         talloc_free(tmp_ctx);
2126
2127         return status;
2128 }
2129
2130 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2131                                   struct pipes_struct *p,
2132                                   struct spoolss_DeletePrinterDriverEx *r,
2133                                   struct dcerpc_binding_handle *b,
2134                                   struct spoolss_DriverInfo8 *info)
2135 {
2136         WERROR status;
2137         bool delete_files;
2138
2139         if (printer_driver_in_use(mem_ctx, b, info)) {
2140                 status = WERR_PRINTER_DRIVER_IN_USE;
2141                 goto done;
2142         }
2143
2144         /*
2145          * we have a couple of cases to consider.
2146          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2147          *     then the delete should fail if **any** files overlap with
2148          *     other drivers
2149          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2150          *     non-overlapping files
2151          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2152          *     are set, then do not delete any files
2153          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2154          */
2155
2156         delete_files = r->in.delete_flags
2157                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2158
2159
2160         if (delete_files) {
2161                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2162                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2163                         status = WERR_PRINTER_DRIVER_IN_USE;
2164                         goto done;
2165                 }
2166                 /*
2167                  * printer_driver_files_in_use() has trimmed overlapping files
2168                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2169                  */
2170         }
2171
2172
2173         status = winreg_del_driver(mem_ctx, b, info, info->version);
2174         if (!W_ERROR_IS_OK(status)) {
2175                 goto done;
2176         }
2177
2178         /*
2179          * now delete any associated files if delete_files is
2180          * true. Even if this part failes, we return succes
2181          * because the driver doesn not exist any more
2182          */
2183         if (delete_files) {
2184                 delete_driver_files(p->session_info, info);
2185         }
2186
2187 done:
2188         return status;
2189 }
2190
2191 /****************************************************************
2192  _spoolss_DeletePrinterDriverEx
2193 ****************************************************************/
2194
2195 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2196                                       struct spoolss_DeletePrinterDriverEx *r)
2197 {
2198         struct spoolss_DriverInfo8 *info = NULL;
2199         WERROR                          status;
2200         struct dcerpc_binding_handle *b;
2201         TALLOC_CTX *tmp_ctx = NULL;
2202         int i;
2203         bool found;
2204
2205         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2206            and not a printer admin, then fail */
2207
2208         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2209             !security_token_has_privilege(p->session_info->security_token,
2210                                           SEC_PRIV_PRINT_OPERATOR)) {
2211                 return WERR_ACCESS_DENIED;
2212         }
2213
2214         /* check that we have a valid driver name first */
2215         if (get_version_id(r->in.architecture) == -1) {
2216                 /* this is what NT returns */
2217                 return WERR_INVALID_ENVIRONMENT;
2218         }
2219
2220         tmp_ctx = talloc_new(p->mem_ctx);
2221         if (!tmp_ctx) {
2222                 return WERR_NOMEM;
2223         }
2224
2225         status = winreg_printer_binding_handle(tmp_ctx,
2226                                                get_session_info_system(),
2227                                                p->msg_ctx,
2228                                                &b);
2229         if (!W_ERROR_IS_OK(status)) {
2230                 goto done;
2231         }
2232
2233         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2234                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2235                  && (drv_cversion[i] != r->in.version)) {
2236                         continue;
2237                 }
2238
2239                 /* check if a driver with this version exists before delete */
2240                 status = winreg_get_driver(tmp_ctx, b,
2241                                            r->in.architecture, r->in.driver,
2242                                            drv_cversion[i], &info);
2243                 if (!W_ERROR_IS_OK(status)) {
2244                         DEBUG(5, ("skipping del of driver with version %d\n",
2245                                   drv_cversion[i]));
2246                         continue;
2247                 }
2248                 found = true;
2249
2250                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2251                 if (!W_ERROR_IS_OK(status)) {
2252                         DEBUG(0, ("failed to delete driver with version %d\n",
2253                                   drv_cversion[i]));
2254                         goto done;
2255                 }
2256         }
2257         if (found == false) {
2258                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2259                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2260         } else {
2261                 status = WERR_OK;
2262         }
2263
2264 done:
2265         talloc_free(tmp_ctx);
2266         return status;
2267 }
2268
2269
2270 /********************************************************************
2271  GetPrinterData on a printer server Handle.
2272 ********************************************************************/
2273
2274 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2275                                             const char *value,
2276                                             enum winreg_Type *type,
2277                                             union spoolss_PrinterData *data)
2278 {
2279         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2280
2281         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2282                 *type = REG_DWORD;
2283                 SIVAL(&data->value, 0, 0x00);
2284                 return WERR_OK;
2285         }
2286
2287         if (!strcasecmp_m(value, "BeepEnabled")) {
2288                 *type = REG_DWORD;
2289                 SIVAL(&data->value, 0, 0x00);
2290                 return WERR_OK;
2291         }
2292
2293         if (!strcasecmp_m(value, "EventLog")) {
2294                 *type = REG_DWORD;
2295                 /* formally was 0x1b */
2296                 SIVAL(&data->value, 0, 0x00);
2297                 return WERR_OK;
2298         }
2299
2300         if (!strcasecmp_m(value, "NetPopup")) {
2301                 *type = REG_DWORD;
2302                 SIVAL(&data->value, 0, 0x00);
2303                 return WERR_OK;
2304         }
2305
2306         if (!strcasecmp_m(value, "MajorVersion")) {
2307                 *type = REG_DWORD;
2308
2309                 /* Windows NT 4.0 seems to not allow uploading of drivers
2310                    to a server that reports 0x3 as the MajorVersion.
2311                    need to investigate more how Win2k gets around this .
2312                    -- jerry */
2313
2314                 if (RA_WINNT == get_remote_arch()) {
2315                         SIVAL(&data->value, 0, 0x02);
2316                 } else {
2317                         SIVAL(&data->value, 0, 0x03);
2318                 }
2319
2320                 return WERR_OK;
2321         }
2322
2323         if (!strcasecmp_m(value, "MinorVersion")) {
2324                 *type = REG_DWORD;
2325                 SIVAL(&data->value, 0, 0x00);
2326                 return WERR_OK;
2327         }
2328
2329         /* REG_BINARY
2330          *  uint32_t size        = 0x114
2331          *  uint32_t major       = 5
2332          *  uint32_t minor       = [0|1]
2333          *  uint32_t build       = [2195|2600]
2334          *  extra unicode string = e.g. "Service Pack 3"
2335          */
2336         if (!strcasecmp_m(value, "OSVersion")) {
2337                 DATA_BLOB blob;
2338                 enum ndr_err_code ndr_err;
2339                 struct spoolss_OSVersion os;
2340
2341                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
2342                                                       "spoolss", "os_major", 5);
2343                                                       /* Windows 2000 == 5.0 */
2344                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
2345                                                       "spoolss", "os_minor", 0);
2346                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
2347                                                       "spoolss", "os_build", 2195);
2348                 os.extra_string         = "";   /* leave extra string empty */
2349
2350                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2351                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2352                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2353                         return WERR_GENERAL_FAILURE;
2354                 }
2355
2356                 if (DEBUGLEVEL >= 10) {
2357                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2358                 }
2359
2360                 *type = REG_BINARY;
2361                 data->binary = blob;
2362
2363                 return WERR_OK;
2364         }
2365
2366
2367         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2368                 *type = REG_SZ;
2369
2370                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2371                 W_ERROR_HAVE_NO_MEMORY(data->string);
2372
2373                 return WERR_OK;
2374         }
2375
2376         if (!strcasecmp_m(value, "Architecture")) {
2377                 *type = REG_SZ;
2378                 data->string = talloc_strdup(mem_ctx,
2379                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2380                 W_ERROR_HAVE_NO_MEMORY(data->string);
2381
2382                 return WERR_OK;
2383         }
2384
2385         if (!strcasecmp_m(value, "DsPresent")) {
2386                 *type = REG_DWORD;
2387
2388                 /* only show the publish check box if we are a
2389                    member of a AD domain */
2390
2391                 if (lp_security() == SEC_ADS) {
2392                         SIVAL(&data->value, 0, 0x01);
2393                 } else {
2394                         SIVAL(&data->value, 0, 0x00);
2395                 }
2396                 return WERR_OK;
2397         }
2398
2399         if (!strcasecmp_m(value, "DNSMachineName")) {
2400                 const char *hostname = get_mydnsfullname();
2401
2402                 if (!hostname) {
2403                         return WERR_BADFILE;
2404                 }
2405
2406                 *type = REG_SZ;
2407                 data->string = talloc_strdup(mem_ctx, hostname);
2408                 W_ERROR_HAVE_NO_MEMORY(data->string);
2409
2410                 return WERR_OK;
2411         }
2412
2413         *type = REG_NONE;
2414
2415         return WERR_INVALID_PARAM;
2416 }
2417
2418 /****************************************************************
2419  _spoolss_GetPrinterData
2420 ****************************************************************/
2421
2422 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2423                                struct spoolss_GetPrinterData *r)
2424 {
2425         struct spoolss_GetPrinterDataEx r2;
2426
2427         r2.in.handle            = r->in.handle;
2428         r2.in.key_name          = "PrinterDriverData";
2429         r2.in.value_name        = r->in.value_name;
2430         r2.in.offered           = r->in.offered;
2431         r2.out.type             = r->out.type;
2432         r2.out.data             = r->out.data;
2433         r2.out.needed           = r->out.needed;
2434
2435         return _spoolss_GetPrinterDataEx(p, &r2);
2436 }
2437
2438 /*********************************************************
2439  Connect to the client machine.
2440 **********************************************************/
2441
2442 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2443                         struct sockaddr_storage *client_ss, const char *remote_machine)
2444 {
2445         NTSTATUS ret;
2446         struct cli_state *the_cli;
2447         struct sockaddr_storage rm_addr;
2448         char addr[INET6_ADDRSTRLEN];
2449
2450         if ( is_zero_addr(client_ss) ) {
2451                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2452                         remote_machine));
2453                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2454                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2455                         return false;
2456                 }
2457                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2458         } else {
2459                 rm_addr = *client_ss;
2460                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2461                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2462                         addr));
2463         }
2464
2465         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2466                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2467                         addr));
2468                 return false;
2469         }
2470
2471         /* setup the connection */
2472         ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2473                 &rm_addr, 0, "IPC$", "IPC",
2474                 "", /* username */
2475                 "", /* domain */
2476                 "", /* password */
2477                 0, lp_client_signing());
2478
2479         if ( !NT_STATUS_IS_OK( ret ) ) {
2480                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2481                         remote_machine ));
2482                 return false;
2483         }
2484
2485         if ( smbXcli_conn_protocol(the_cli->conn) != PROTOCOL_NT1 ) {
2486                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2487                 cli_shutdown(the_cli);
2488                 return false;
2489         }
2490
2491         /*
2492          * Ok - we have an anonymous connection to the IPC$ share.
2493          * Now start the NT Domain stuff :-).
2494          */
2495
2496         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2497         if (!NT_STATUS_IS_OK(ret)) {
2498                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2499                         remote_machine, nt_errstr(ret)));
2500                 cli_shutdown(the_cli);
2501                 return false;
2502         }
2503
2504         return true;
2505 }
2506
2507 /***************************************************************************
2508  Connect to the client.
2509 ****************************************************************************/
2510
2511 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2512                                         uint32_t localprinter,
2513                                         enum winreg_Type type,
2514                                         struct policy_handle *handle,
2515                                         struct notify_back_channel **_chan,
2516                                         struct sockaddr_storage *client_ss,
2517                                         struct messaging_context *msg_ctx)
2518 {
2519         WERROR result;
2520         NTSTATUS status;
2521         struct notify_back_channel *chan;
2522
2523         for (chan = back_channels; chan; chan = chan->next) {
2524                 if (memcmp(&chan->client_address, client_ss,
2525                            sizeof(struct sockaddr_storage)) == 0) {
2526                         break;
2527                 }
2528         }
2529
2530         /*
2531          * If it's the first connection, contact the client
2532          * and connect to the IPC$ share anonymously
2533          */
2534         if (!chan) {
2535                 fstring unix_printer;
2536
2537                 /* the +2 is to strip the leading 2 backslashs */
2538                 fstrcpy(unix_printer, printer + 2);
2539
2540                 chan = talloc_zero(NULL, struct notify_back_channel);
2541                 if (!chan) {
2542                         return false;
2543                 }
2544                 chan->client_address = *client_ss;
2545
2546                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2547                         TALLOC_FREE(chan);
2548                         return false;
2549                 }
2550
2551                 DLIST_ADD(back_channels, chan);
2552
2553                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2554                                    receive_notify2_message_list);
2555         }
2556
2557         if (chan->cli_pipe == NULL ||
2558             chan->cli_pipe->binding_handle == NULL) {
2559                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2560                         "NULL %s for printer %s\n",
2561                         chan->cli_pipe == NULL ?
2562                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2563                         printer));
2564                 return false;
2565         }
2566
2567         /*
2568          * Tell the specific printing tdb we want messages for this printer
2569          * by registering our PID.
2570          */
2571
2572         if (!print_notify_register_pid(snum)) {
2573                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2574                           printer));
2575         }
2576
2577         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2578                                                  talloc_tos(),
2579                                                  printer,
2580                                                  localprinter,
2581                                                  type,
2582                                                  0,
2583                                                  NULL,
2584                                                  handle,
2585                                                  &result);
2586         if (!NT_STATUS_IS_OK(status)) {
2587                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2588                 result = ntstatus_to_werror(status);
2589         } else if (!W_ERROR_IS_OK(result)) {
2590                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2591         }
2592
2593         chan->active_connections++;
2594         *_chan = chan;
2595
2596         return (W_ERROR_IS_OK(result));
2597 }
2598
2599 /****************************************************************
2600  ****************************************************************/
2601
2602 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2603                                                              const struct spoolss_NotifyOption *r)
2604 {
2605         struct spoolss_NotifyOption *option;
2606         uint32_t i,k;
2607
2608         if (!r) {
2609                 return NULL;
2610         }
2611
2612         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2613         if (!option) {
2614                 return NULL;
2615         }
2616
2617         *option = *r;
2618
2619         if (!option->count) {
2620                 return option;
2621         }
2622
2623         option->types = talloc_zero_array(option,
2624                 struct spoolss_NotifyOptionType, option->count);
2625         if (!option->types) {
2626                 talloc_free(option);
2627                 return NULL;
2628         }
2629
2630         for (i=0; i < option->count; i++) {
2631                 option->types[i] = r->types[i];
2632
2633                 if (option->types[i].count) {
2634                         option->types[i].fields = talloc_zero_array(option,
2635                                 union spoolss_Field, option->types[i].count);
2636                         if (!option->types[i].fields) {
2637                                 talloc_free(option);
2638                                 return NULL;
2639                         }
2640                         for (k=0; k<option->types[i].count; k++) {
2641                                 option->types[i].fields[k] =
2642                                         r->types[i].fields[k];
2643                         }
2644                 }
2645         }
2646
2647         return option;
2648 }
2649
2650 /****************************************************************
2651  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2652  *
2653  * before replying OK: status=0 a rpc call is made to the workstation
2654  * asking ReplyOpenPrinter
2655  *
2656  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2657  * called from api_spoolss_rffpcnex
2658 ****************************************************************/
2659
2660 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2661                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2662 {
2663         int snum = -1;
2664         struct spoolss_NotifyOption *option = r->in.notify_options;
2665         struct sockaddr_storage client_ss;
2666         ssize_t client_len;
2667
2668         /* store the notify value in the printer struct */
2669
2670         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2671
2672         if (!Printer) {
2673                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2674                         "Invalid handle (%s:%u:%u).\n",
2675                         OUR_HANDLE(r->in.handle)));
2676                 return WERR_BADFID;
2677         }
2678
2679         Printer->notify.flags           = r->in.flags;
2680         Printer->notify.options         = r->in.options;
2681         Printer->notify.printerlocal    = r->in.printer_local;
2682         Printer->notify.msg_ctx         = p->msg_ctx;
2683
2684         TALLOC_FREE(Printer->notify.option);
2685         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2686
2687         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2688
2689         /* Connect to the client machine and send a ReplyOpenPrinter */
2690
2691         if ( Printer->printer_type == SPLHND_SERVER)
2692                 snum = -1;
2693         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2694                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2695                 return WERR_BADFID;
2696
2697         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2698                   "remote_address is %s\n",
2699                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2700
2701         if (!lp_print_notify_backchannel(snum)) {
2702                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2703                         "backchannel disabled\n"));
2704                 return WERR_SERVER_UNAVAILABLE;
2705         }
2706
2707         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2708                                                   (struct sockaddr *) &client_ss,
2709                                                   sizeof(struct sockaddr_storage));
2710         if (client_len < 0) {
2711                 return WERR_NOMEM;
2712         }
2713
2714         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2715                                         Printer->notify.printerlocal, REG_SZ,
2716                                         &Printer->notify.cli_hnd,
2717                                         &Printer->notify.cli_chan,
2718                                         &client_ss, p->msg_ctx)) {
2719                 return WERR_SERVER_UNAVAILABLE;
2720         }
2721
2722         return WERR_OK;
2723 }
2724
2725 /*******************************************************************
2726  * fill a notify_info_data with the servername
2727  ********************************************************************/
2728
2729 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2730                                        int snum,
2731                                        struct spoolss_Notify *data,
2732                                        print_queue_struct *queue,
2733                                        struct spoolss_PrinterInfo2 *pinfo2,
2734                                        TALLOC_CTX *mem_ctx)
2735 {
2736         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2737 }
2738
2739 /*******************************************************************
2740  * fill a notify_info_data with the printername (not including the servername).
2741  ********************************************************************/
2742
2743 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2744                                         int snum,
2745                                         struct spoolss_Notify *data,
2746                                         print_queue_struct *queue,
2747                                         struct spoolss_PrinterInfo2 *pinfo2,
2748                                         TALLOC_CTX *mem_ctx)
2749 {
2750         /* the notify name should not contain the \\server\ part */
2751         const char *p = strrchr(pinfo2->printername, '\\');
2752
2753         if (!p) {
2754                 p = pinfo2->printername;
2755         } else {
2756                 p++;
2757         }
2758
2759         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2760 }
2761
2762 /*******************************************************************
2763  * fill a notify_info_data with the servicename
2764  ********************************************************************/
2765
2766 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2767                                       int snum,
2768                                       struct spoolss_Notify *data,
2769                                       print_queue_struct *queue,
2770                                       struct spoolss_PrinterInfo2 *pinfo2,
2771                                       TALLOC_CTX *mem_ctx)
2772 {
2773         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2774 }
2775
2776 /*******************************************************************
2777  * fill a notify_info_data with the port name
2778  ********************************************************************/
2779
2780 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2781                                      int snum,
2782                                      struct spoolss_Notify *data,
2783                                      print_queue_struct *queue,
2784                                      struct spoolss_PrinterInfo2 *pinfo2,
2785                                      TALLOC_CTX *mem_ctx)
2786 {
2787         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2788 }
2789
2790 /*******************************************************************
2791  * fill a notify_info_data with the printername
2792  * but it doesn't exist, have to see what to do
2793  ********************************************************************/
2794
2795 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2796                                        int snum,
2797                                        struct spoolss_Notify *data,
2798                                        print_queue_struct *queue,
2799                                        struct spoolss_PrinterInfo2 *pinfo2,
2800                                        TALLOC_CTX *mem_ctx)
2801 {
2802         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2803 }
2804
2805 /*******************************************************************
2806  * fill a notify_info_data with the comment
2807  ********************************************************************/
2808
2809 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2810                                    int snum,
2811                                    struct spoolss_Notify *data,
2812                                    print_queue_struct *queue,
2813                                    struct spoolss_PrinterInfo2 *pinfo2,
2814                                    TALLOC_CTX *mem_ctx)
2815 {
2816         const char *p;
2817
2818         if (*pinfo2->comment == '\0') {
2819                 p = lp_comment(talloc_tos(), snum);
2820         } else {
2821                 p = pinfo2->comment;
2822         }
2823
2824         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2825 }
2826
2827 /*******************************************************************
2828  * fill a notify_info_data with the comment
2829  * location = "Room 1, floor 2, building 3"
2830  ********************************************************************/
2831
2832 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2833                                     int snum,
2834                                     struct spoolss_Notify *data,
2835                                     print_queue_struct *queue,
2836                                     struct spoolss_PrinterInfo2 *pinfo2,
2837                                     TALLOC_CTX *mem_ctx)
2838 {
2839         const char *loc = pinfo2->location;
2840         NTSTATUS status;
2841
2842         status = printer_list_get_printer(mem_ctx,
2843                                           pinfo2->sharename,
2844                                           NULL,
2845                                           &loc,
2846                                           NULL);
2847         if (NT_STATUS_IS_OK(status)) {
2848                 if (loc == NULL) {
2849                         loc = pinfo2->location;
2850                 }
2851         }
2852
2853         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2854 }
2855
2856 /*******************************************************************
2857  * fill a notify_info_data with the device mode
2858  * jfm:xxxx don't to it for know but that's a real problem !!!
2859  ********************************************************************/
2860
2861 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2862                                    int snum,
2863                                    struct spoolss_Notify *data,
2864                                    print_queue_struct *queue,
2865                                    struct spoolss_PrinterInfo2 *pinfo2,
2866                                    TALLOC_CTX *mem_ctx)
2867 {
2868         /* for a dummy implementation we have to zero the fields */
2869         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2870 }
2871
2872 /*******************************************************************
2873  * fill a notify_info_data with the separator file name
2874  ********************************************************************/
2875
2876 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2877                                    int snum,
2878                                    struct spoolss_Notify *data,
2879                                    print_queue_struct *queue,
2880                                    struct spoolss_PrinterInfo2 *pinfo2,
2881                                    TALLOC_CTX *mem_ctx)
2882 {
2883         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2884 }
2885
2886 /*******************************************************************
2887  * fill a notify_info_data with the print processor
2888  * jfm:xxxx return always winprint to indicate we don't do anything to it
2889  ********************************************************************/
2890
2891 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2892                                            int snum,
2893                                            struct spoolss_Notify *data,
2894                                            print_queue_struct *queue,
2895                                            struct spoolss_PrinterInfo2 *pinfo2,
2896                                            TALLOC_CTX *mem_ctx)
2897 {
2898         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2899 }
2900
2901 /*******************************************************************
2902  * fill a notify_info_data with the print processor options
2903  * jfm:xxxx send an empty string
2904  ********************************************************************/
2905
2906 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2907                                       int snum,
2908                                       struct spoolss_Notify *data,
2909                                       print_queue_struct *queue,
2910                                       struct spoolss_PrinterInfo2 *pinfo2,
2911                                       TALLOC_CTX *mem_ctx)
2912 {
2913         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2914 }
2915
2916 /*******************************************************************
2917  * fill a notify_info_data with the data type
2918  * jfm:xxxx always send RAW as data type
2919  ********************************************************************/
2920
2921 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2922                                     int snum,
2923                                     struct spoolss_Notify *data,
2924                                     print_queue_struct *queue,
2925                                     struct spoolss_PrinterInfo2 *pinfo2,
2926                                     TALLOC_CTX *mem_ctx)
2927 {
2928         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2929 }
2930
2931 /*******************************************************************
2932  * fill a notify_info_data with the security descriptor
2933  * jfm:xxxx send an null pointer to say no security desc
2934  * have to implement security before !
2935  ********************************************************************/
2936
2937 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2938                                          int snum,
2939                                          struct spoolss_Notify *data,
2940                                          print_queue_struct *queue,
2941                                          struct spoolss_PrinterInfo2 *pinfo2,
2942                                          TALLOC_CTX *mem_ctx)
2943 {
2944         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2945 }
2946
2947 /*******************************************************************
2948  * fill a notify_info_data with the attributes
2949  * jfm:xxxx a samba printer is always shared
2950  ********************************************************************/
2951
2952 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2953                                       int snum,
2954                                       struct spoolss_Notify *data,
2955                                       print_queue_struct *queue,
2956                                       struct spoolss_PrinterInfo2 *pinfo2,
2957                                       TALLOC_CTX *mem_ctx)
2958 {
2959         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2960 }
2961
2962 /*******************************************************************
2963  * fill a notify_info_data with the priority
2964  ********************************************************************/
2965
2966 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2967                                     int snum,
2968                                     struct spoolss_Notify *data,
2969                                     print_queue_struct *queue,
2970                                     struct spoolss_PrinterInfo2 *pinfo2,
2971                                     TALLOC_CTX *mem_ctx)
2972 {
2973         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2974 }
2975
2976 /*******************************************************************
2977  * fill a notify_info_data with the default priority
2978  ********************************************************************/
2979
2980 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2981                                             int snum,
2982                                             struct spoolss_Notify *data,
2983                                             print_queue_struct *queue,
2984                                             struct spoolss_PrinterInfo2 *pinfo2,
2985                                             TALLOC_CTX *mem_ctx)
2986 {
2987         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2988 }
2989
2990 /*******************************************************************
2991  * fill a notify_info_data with the start time
2992  ********************************************************************/
2993
2994 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2995                                       int snum,
2996                                       struct spoolss_Notify *data,
2997                                       print_queue_struct *queue,
2998                                       struct spoolss_PrinterInfo2 *pinfo2,
2999                                       TALLOC_CTX *mem_ctx)
3000 {
3001         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3002 }
3003
3004 /*******************************************************************
3005  * fill a notify_info_data with the until time
3006  ********************************************************************/
3007
3008 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3009                                       int snum,
3010                                       struct spoolss_Notify *data,
3011                                       print_queue_struct *queue,
3012                                       struct spoolss_PrinterInfo2 *pinfo2,
3013                                       TALLOC_CTX *mem_ctx)
3014 {
3015         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3016 }
3017
3018 /*******************************************************************
3019  * fill a notify_info_data with the status
3020  ********************************************************************/
3021
3022 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3023                                   int snum,
3024                                   struct spoolss_Notify *data,
3025                                   print_queue_struct *queue,
3026                                   struct spoolss_PrinterInfo2 *pinfo2,
3027                                   TALLOC_CTX *mem_ctx)
3028 {
3029         print_status_struct status;
3030
3031         print_queue_length(msg_ctx, snum, &status);
3032         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3033 }
3034
3035 /*******************************************************************
3036  * fill a notify_info_data with the number of jobs queued
3037  ********************************************************************/
3038
3039 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3040                                  int snum,
3041                                  struct spoolss_Notify *data,
3042                                  print_queue_struct *queue,
3043                                  struct spoolss_PrinterInfo2 *pinfo2,
3044                                  TALLOC_CTX *mem_ctx)
3045 {
3046         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3047                 data, print_queue_length(msg_ctx, snum, NULL));
3048 }
3049
3050 /*******************************************************************
3051  * fill a notify_info_data with the average ppm
3052  ********************************************************************/
3053
3054 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3055                                        int snum,
3056                                        struct spoolss_Notify *data,
3057                                        print_queue_struct *queue,
3058                                        struct spoolss_PrinterInfo2 *pinfo2,
3059                                        TALLOC_CTX *mem_ctx)
3060 {
3061         /* always respond 8 pages per minutes */
3062         /* a little hard ! */
3063         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3064 }
3065
3066 /*******************************************************************
3067  * fill a notify_info_data with username
3068  ********************************************************************/
3069
3070 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3071                                     int snum,
3072                                     struct spoolss_Notify *data,
3073                                     print_queue_struct *queue,
3074                                     struct spoolss_PrinterInfo2 *pinfo2,
3075                                     TALLOC_CTX *mem_ctx)
3076 {
3077         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3078 }
3079
3080 /*******************************************************************
3081  * fill a notify_info_data with job status
3082  ********************************************************************/
3083
3084 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3085                                       int snum,
3086                                       struct spoolss_Notify *data,
3087                                       print_queue_struct *queue,
3088                                       struct spoolss_PrinterInfo2 *pinfo2,
3089                                       TALLOC_CTX *mem_ctx)
3090 {
3091         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3092 }
3093
3094 /*******************************************************************
3095  * fill a notify_info_data with job name
3096  ********************************************************************/
3097
3098 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3099                                     int snum,
3100                                     struct spoolss_Notify *data,
3101                                     print_queue_struct *queue,
3102                                     struct spoolss_PrinterInfo2 *pinfo2,
3103                                     TALLOC_CTX *mem_ctx)
3104 {
3105         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3106 }
3107
3108 /*******************************************************************
3109  * fill a notify_info_data with job status
3110  ********************************************************************/
3111
3112 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3113                                              int snum,
3114                                              struct spoolss_Notify *data,
3115                                              print_queue_struct *queue,
3116                                              struct spoolss_PrinterInfo2 *pinfo2,
3117                                              TALLOC_CTX *mem_ctx)
3118 {
3119         /*
3120          * Now we're returning job status codes we just return a "" here. JRA.
3121          */
3122
3123         const char *p = "";
3124
3125 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3126         p = "unknown";
3127
3128         switch (queue->status) {
3129         case LPQ_QUEUED:
3130                 p = "Queued";
3131                 break;
3132         case LPQ_PAUSED:
3133                 p = "";    /* NT provides the paused string */
3134                 break;
3135         case LPQ_SPOOLING:
3136                 p = "Spooling";
3137                 break;
3138         case LPQ_PRINTING:
3139                 p = "Printing";
3140                 break;
3141         }
3142 #endif /* NO LONGER NEEDED. */
3143
3144         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3145 }
3146
3147 /*******************************************************************
3148  * fill a notify_info_data with job time
3149  ********************************************************************/
3150
3151 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3152                                     int snum,
3153                                     struct spoolss_Notify *data,
3154                                     print_queue_struct *queue,
3155                                     struct spoolss_PrinterInfo2 *pinfo2,
3156                                     TALLOC_CTX *mem_ctx)
3157 {
3158         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3159 }
3160
3161 /*******************************************************************
3162  * fill a notify_info_data with job size
3163  ********************************************************************/
3164
3165 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3166                                     int snum,
3167                                     struct spoolss_Notify *data,
3168                                     print_queue_struct *queue,
3169                                     struct spoolss_PrinterInfo2 *pinfo2,
3170                                     TALLOC_CTX *mem_ctx)
3171 {
3172         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3173 }
3174
3175 /*******************************************************************
3176  * fill a notify_info_data with page info
3177  ********************************************************************/
3178 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3179                                        int snum,
3180                                 struct spoolss_Notify *data,
3181                                 print_queue_struct *queue,
3182                                 struct spoolss_PrinterInfo2 *pinfo2,
3183                                 TALLOC_CTX *mem_ctx)
3184 {
3185         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3186 }
3187
3188 /*******************************************************************
3189  * fill a notify_info_data with pages printed info.
3190  ********************************************************************/
3191 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3192                                          int snum,
3193                                 struct spoolss_Notify *data,
3194                                 print_queue_struct *queue,
3195                                 struct spoolss_PrinterInfo2 *pinfo2,
3196                                 TALLOC_CTX *mem_ctx)
3197 {
3198         /* Add code when back-end tracks this */
3199         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3200 }
3201
3202 /*******************************************************************
3203  Fill a notify_info_data with job position.
3204  ********************************************************************/
3205
3206 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3207                                         int snum,
3208                                         struct spoolss_Notify *data,
3209                                         print_queue_struct *queue,
3210                                         struct spoolss_PrinterInfo2 *pinfo2,
3211                                         TALLOC_CTX *mem_ctx)
3212 {
3213         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3214 }
3215
3216 /*******************************************************************
3217  Fill a notify_info_data with submitted time.
3218  ********************************************************************/
3219
3220 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3221                                           int snum,
3222                                           struct spoolss_Notify *data,
3223                                           print_queue_struct *queue,
3224                                           struct spoolss_PrinterInfo2 *pinfo2,
3225                                           TALLOC_CTX *mem_ctx)
3226 {
3227         data->data.string.string = NULL;
3228         data->data.string.size = 0;
3229
3230         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3231                                &data->data.string.string,
3232                                &data->data.string.size);
3233
3234 }
3235
3236 struct s_notify_info_data_table
3237 {
3238         enum spoolss_NotifyType type;
3239         uint16_t field;
3240         const char *name;
3241         enum spoolss_NotifyTable variable_type;
3242         void (*fn) (struct messaging_context *msg_ctx,
3243                     int snum, struct spoolss_Notify *data,
3244                     print_queue_struct *queue,
3245                     struct spoolss_PrinterInfo2 *pinfo2,
3246                     TALLOC_CTX *mem_ctx);
3247 };
3248
3249 /* A table describing the various print notification constants and
3250    whether the notification data is a pointer to a variable sized
3251    buffer, a one value uint32_t or a two value uint32_t. */
3252
3253 static const struct s_notify_info_data_table notify_info_data_table[] =
3254 {
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3281 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3282 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3283 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3284 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3285 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3286 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3287 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3288 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3289 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3290 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3291 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3304 };
3305
3306 /*******************************************************************
3307  Return the variable_type of info_data structure.
3308 ********************************************************************/
3309
3310 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3311                                                                   uint16_t field)
3312 {
3313         int i=0;
3314
3315         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3316                 if ( (notify_info_data_table[i].type == type) &&
3317                      (notify_info_data_table[i].field == field) ) {
3318                         return notify_info_data_table[i].variable_type;
3319                 }
3320         }
3321
3322         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3323
3324         return (enum spoolss_NotifyTable) 0;
3325 }
3326
3327 /****************************************************************************
3328 ****************************************************************************/
3329
3330 static bool search_notify(enum spoolss_NotifyType type,
3331                           uint16_t field,
3332                           int *value)
3333 {
3334         int i;
3335
3336         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3337                 if (notify_info_data_table[i].type == type &&
3338                     notify_info_data_table[i].field == field &&
3339                     notify_info_data_table[i].fn != NULL) {
3340                         *value = i;
3341                         return true;
3342                 }
3343         }
3344
3345         return false;
3346 }
3347
3348 /****************************************************************************
3349 ****************************************************************************/
3350
3351 static void construct_info_data(struct spoolss_Notify *info_data,
3352                                 enum spoolss_NotifyType type,
3353                                 uint16_t field, int id)
3354 {
3355         info_data->type                 = type;
3356         info_data->field.field          = field;
3357         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3358         info_data->job_id               = id;
3359 }
3360
3361 /*******************************************************************
3362  *
3363  * fill a notify_info struct with info asked
3364  *
3365  ********************************************************************/
3366
3367 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3368                                           struct printer_handle *print_hnd,
3369                                           struct spoolss_NotifyInfo *info,
3370                                           struct spoolss_PrinterInfo2 *pinfo2,
3371                                           int snum,
3372                                           const struct spoolss_NotifyOptionType *option_type,
3373                                           uint32_t id,
3374                                           TALLOC_CTX *mem_ctx)
3375 {
3376         int field_num,j;
3377         enum spoolss_NotifyType type;
3378         uint16_t field;
3379
3380         struct spoolss_Notify *current_data;
3381
3382         type = option_type->type;
3383
3384         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3385                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3386                 option_type->count, lp_servicename(talloc_tos(), snum)));
3387
3388         for(field_num=0; field_num < option_type->count; field_num++) {
3389                 field = option_type->fields[field_num].field;
3390
3391                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3392
3393                 if (!search_notify(type, field, &j) )
3394                         continue;
3395
3396                 info->notifies = talloc_realloc(info, info->notifies,
3397                                                       struct spoolss_Notify,
3398                                                       info->count + 1);
3399                 if (info->notifies == NULL) {
3400                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3401                         return false;
3402                 }
3403
3404                 current_data = &info->notifies[info->count];
3405
3406                 construct_info_data(current_data, type, field, id);
3407
3408                 DEBUG(10, ("construct_notify_printer_info: "
3409                            "calling [%s]  snum=%d  printername=[%s])\n",
3410                            notify_info_data_table[j].name, snum,
3411                            pinfo2->printername));
3412
3413                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3414                                              NULL, pinfo2, mem_ctx);
3415
3416                 info->count++;
3417         }
3418
3419         return true;
3420 }
3421
3422 /*******************************************************************
3423  *
3424  * fill a notify_info struct with info asked
3425  *
3426  ********************************************************************/
3427
3428 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3429                                        print_queue_struct *queue,
3430                                        struct spoolss_NotifyInfo *info,
3431                                        struct spoolss_PrinterInfo2 *pinfo2,
3432                                        int snum,
3433                                        const struct spoolss_NotifyOptionType *option_type,
3434                                        uint32_t id,
3435                                        TALLOC_CTX *mem_ctx)
3436 {
3437         int field_num,j;
3438         enum spoolss_NotifyType type;
3439         uint16_t field;
3440         struct spoolss_Notify *current_data;
3441
3442         DEBUG(4,("construct_notify_jobs_info\n"));
3443
3444         type = option_type->type;
3445
3446         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3447                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3448                 option_type->count));
3449
3450         for(field_num=0; field_num<option_type->count; field_num++) {
3451                 field = option_type->fields[field_num].field;
3452
3453                 if (!search_notify(type, field, &j) )
3454                         continue;
3455
3456                 info->notifies = talloc_realloc(info, info->notifies,
3457                                                       struct spoolss_Notify,
3458                                                       info->count + 1);
3459                 if (info->notifies == NULL) {
3460                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3461                         return false;
3462                 }
3463
3464                 current_data=&(info->notifies[info->count]);
3465
3466                 construct_info_data(current_data, type, field, id);
3467                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3468                                              queue, pinfo2, mem_ctx);
3469                 info->count++;
3470         }
3471
3472         return true;
3473 }
3474
3475 /*
3476  * JFM: The enumeration is not that simple, it's even non obvious.
3477  *
3478  * let's take an example: I want to monitor the PRINTER SERVER for
3479  * the printer's name and the number of jobs currently queued.
3480  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3481  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3482  *
3483  * I have 3 printers on the back of my server.
3484  *
3485  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3486  * structures.
3487  *   Number     Data                    Id
3488  *      1       printer 1 name          1
3489  *      2       printer 1 cjob          1
3490  *      3       printer 2 name          2
3491  *      4       printer 2 cjob          2
3492  *      5       printer 3 name          3
3493  *      6       printer 3 name          3
3494  *
3495  * that's the print server case, the printer case is even worse.
3496  */
3497
3498 /*******************************************************************
3499  *
3500  * enumerate all printers on the printserver
3501  * fill a notify_info struct with info asked
3502  *
3503  ********************************************************************/
3504
3505 static WERROR printserver_notify_info(struct pipes_struct *p,
3506                                       struct policy_handle *hnd,
3507                                       struct spoolss_NotifyInfo *info,
3508                                       TALLOC_CTX *mem_ctx)
3509 {
3510         int snum;
3511         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3512         int n_services=lp_numservices();
3513         int i;
3514         struct spoolss_NotifyOption *option;
3515         struct spoolss_NotifyOptionType option_type;
3516         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3517         WERROR result;
3518
3519         DEBUG(4,("printserver_notify_info\n"));
3520
3521         if (!Printer)
3522                 return WERR_BADFID;
3523
3524         option = Printer->notify.option;
3525
3526         info->version   = 2;
3527         info->notifies  = NULL;
3528         info->count     = 0;
3529
3530         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3531            sending a ffpcn() request first */
3532
3533         if ( !option )
3534                 return WERR_BADFID;
3535
3536         for (i=0; i<option->count; i++) {
3537                 option_type = option->types[i];
3538
3539                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3540                         continue;
3541
3542                 for (snum = 0; snum < n_services; snum++) {
3543                         if (!lp_browseable(snum) ||
3544                             !lp_snum_ok(snum) ||
3545                             !lp_print_ok(snum)) {
3546                                 continue; /* skip */
3547                         }
3548
3549                         /* Maybe we should use the SYSTEM session_info here... */
3550                         result = winreg_get_printer_internal(mem_ctx,
3551                                                     get_session_info_system(),
3552                                                     p->msg_ctx,
3553                                                     lp_servicename(talloc_tos(), snum),
3554                                                     &pinfo2);
3555                         if (!W_ERROR_IS_OK(result)) {
3556                                 DEBUG(4, ("printserver_notify_info: "
3557                                           "Failed to get printer [%s]\n",
3558                                           lp_servicename(talloc_tos(), snum)));
3559                                 continue;
3560                         }
3561
3562
3563                         construct_notify_printer_info(p->msg_ctx,
3564                                                       Printer, info,
3565                                                       pinfo2, snum,
3566                                                       &option_type, snum,
3567                                                       mem_ctx);
3568
3569                         TALLOC_FREE(pinfo2);
3570                 }
3571         }
3572
3573 #if 0
3574         /*
3575          * Debugging information, don't delete.
3576          */
3577
3578         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3579         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3580         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3581
3582         for (i=0; i<info->count; i++) {
3583                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3584                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3585                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3586         }
3587 #endif
3588
3589         return WERR_OK;
3590 }
3591
3592 /*******************************************************************
3593  *
3594  * fill a notify_info struct with info asked
3595  *
3596  ********************************************************************/
3597
3598 static WERROR printer_notify_info(struct pipes_struct *p,
3599                                   struct policy_handle *hnd,
3600                                   struct spoolss_NotifyInfo *info,
3601                                   TALLOC_CTX *mem_ctx)
3602 {
3603         int snum;
3604         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3605         int i;
3606         uint32_t id;
3607         struct spoolss_NotifyOption *option;
3608         struct spoolss_NotifyOptionType option_type;
3609         int count,j;
3610         print_queue_struct *queue=NULL;
3611         print_status_struct status;
3612         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3613         WERROR result;
3614
3615         DEBUG(4,("printer_notify_info\n"));
3616
3617         if (!Printer)
3618                 return WERR_BADFID;
3619
3620         option = Printer->notify.option;
3621         id = 0x0;
3622
3623         info->version   = 2;
3624         info->notifies  = NULL;
3625         info->count     = 0;
3626
3627         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3628            sending a ffpcn() request first */
3629
3630         if ( !option )
3631                 return WERR_BADFID;
3632
3633         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3634                 return WERR_BADFID;
3635         }
3636
3637         /* Maybe we should use the SYSTEM session_info here... */
3638         result = winreg_get_printer_internal(mem_ctx,
3639                                     get_session_info_system(),
3640                                     p->msg_ctx,
3641                                     lp_servicename(talloc_tos(), snum), &pinfo2);
3642         if (!W_ERROR_IS_OK(result)) {
3643                 return WERR_BADFID;
3644         }
3645
3646         /*
3647          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3648          * correct servername.
3649          */
3650         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3651         if (pinfo2->servername == NULL) {
3652                 return WERR_NOMEM;
3653         }
3654
3655         for (i=0; i<option->count; i++) {
3656                 option_type = option->types[i];
3657
3658                 switch (option_type.type) {
3659                 case PRINTER_NOTIFY_TYPE:
3660                         if (construct_notify_printer_info(p->msg_ctx,
3661                                                           Printer, info,
3662                                                           pinfo2, snum,
3663                                                           &option_type, id,
3664                                                           mem_ctx)) {
3665                                 id--;
3666                         }
3667                         break;
3668
3669                 case JOB_NOTIFY_TYPE:
3670
3671                         count = print_queue_status(p->msg_ctx, snum, &queue,
3672                                                    &status);
3673
3674                         for (j=0; j<count; j++) {
3675                                 construct_notify_jobs_info(p->msg_ctx,
3676                                                            &queue[j], info,
3677                                                            pinfo2, snum,
3678                                                            &option_type,
3679                                                            queue[j].sysjob,
3680                                                            mem_ctx);
3681                         }
3682
3683                         SAFE_FREE(queue);
3684                         break;
3685                 }
3686         }
3687
3688         /*
3689          * Debugging information, don't delete.
3690          */
3691         /*
3692         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3693         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3694         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3695
3696         for (i=0; i<info->count; i++) {
3697                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3698                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3699                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3700         }
3701         */
3702
3703         talloc_free(pinfo2);
3704         return WERR_OK;
3705 }
3706
3707 /****************************************************************
3708  _spoolss_RouterRefreshPrinterChangeNotify
3709 ****************************************************************/
3710
3711 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3712                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3713 {
3714         struct spoolss_NotifyInfo *info;
3715
3716         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3717         WERROR result = WERR_BADFID;
3718
3719         /* we always have a spoolss_NotifyInfo struct */
3720         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3721         if (!info) {
3722                 result = WERR_NOMEM;
3723                 goto done;
3724         }
3725
3726         *r->out.info = info;
3727
3728         if (!Printer) {
3729                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3730                         "Invalid handle (%s:%u:%u).\n",
3731                         OUR_HANDLE(r->in.handle)));
3732                 goto done;
3733         }
3734
3735         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3736
3737         /*
3738          *      We are now using the change value, and
3739          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3740          *      I don't have a global notification system, I'm sending back all the
3741          *      information even when _NOTHING_ has changed.
3742          */
3743
3744         /* We need to keep track of the change value to send back in
3745            RRPCN replies otherwise our updates are ignored. */
3746
3747         Printer->notify.fnpcn = true;
3748
3749         if (Printer->notify.cli_chan != NULL &&
3750             Printer->notify.cli_chan->active_connections > 0) {
3751                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3752                         "Saving change value in request [%x]\n",
3753                         r->in.change_low));
3754                 Printer->notify.change = r->in.change_low;
3755         }
3756
3757         /* just ignore the spoolss_NotifyOption */
3758
3759         switch (Printer->printer_type) {
3760                 case SPLHND_SERVER:
3761                         result = printserver_notify_info(p, r->in.handle,
3762                                                          info, p->mem_ctx);
3763                         break;
3764
3765                 case SPLHND_PRINTER:
3766                         result = printer_notify_info(p, r->in.handle,
3767                                                      info, p->mem_ctx);
3768                         break;
3769         }
3770
3771         Printer->notify.fnpcn = false;
3772
3773 done:
3774         return result;
3775 }
3776
3777 /********************************************************************
3778  ********************************************************************/
3779
3780 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3781                                  const char *servername,
3782                                  const char *printername,
3783                                  const char **printername_p)
3784 {
3785         /* FIXME: add lp_force_printername() */
3786
3787         if (servername == NULL) {
3788                 *printername_p = talloc_strdup(mem_ctx, printername);
3789                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3790                 return WERR_OK;
3791         }
3792
3793         if (servername[0] == '\\' && servername[1] == '\\') {
3794                 servername += 2;
3795         }
3796
3797         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3798         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3799
3800         return WERR_OK;
3801 }
3802
3803 /********************************************************************
3804  ********************************************************************/
3805
3806 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3807                                           const char *printername)
3808 {
3809         if (dm == NULL) {
3810                 return;
3811         }
3812
3813         dm->devicename = talloc_strndup(dm, printername,
3814                                         MIN(strlen(printername), 31));
3815 }
3816
3817 /********************************************************************
3818  * construct_printer_info_0
3819  * fill a printer_info_0 struct
3820  ********************************************************************/
3821
3822 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3823                                       const struct auth_session_info *session_info,
3824                                       struct messaging_context *msg_ctx,
3825                                       struct spoolss_PrinterInfo2 *info2,
3826                                       const char *servername,
3827                                       struct spoolss_PrinterInfo0 *r,
3828                                       int snum)
3829 {
3830         int count;
3831         struct printer_session_counter *session_counter;
3832         struct timeval setuptime;
3833         print_status_struct status;
3834         WERROR result;
3835
3836         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3837         if (!W_ERROR_IS_OK(result)) {
3838                 return result;
3839         }
3840
3841         if (servername) {
3842                 r->servername = talloc_strdup(mem_ctx, servername);
3843                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3844         } else {
3845                 r->servername = NULL;
3846         }
3847
3848         count = print_queue_length(msg_ctx, snum, &status);
3849
3850         /* check if we already have a counter for this printer */
3851         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3852                 if (session_counter->snum == snum)
3853                         break;
3854         }
3855
3856         /* it's the first time, add it to the list */
3857         if (session_counter == NULL) {
3858                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3859                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3860                 session_counter->snum           = snum;
3861                 session_counter->counter        = 0;
3862                 DLIST_ADD(counter_list, session_counter);
3863         }
3864
3865         /* increment it */
3866         session_counter->counter++;
3867
3868         r->cjobs                        = count;
3869         r->total_jobs                   = 0;
3870         r->total_bytes                  = 0;
3871
3872         get_startup_time(&setuptime);
3873         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3874
3875         /* JFM:
3876          * the global_counter should be stored in a TDB as it's common to all the clients
3877          * and should be zeroed on samba startup
3878          */
3879         r->global_counter               = session_counter->counter;
3880         r->total_pages                  = 0;
3881         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3882         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3883         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3884         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3885         r->spooling                     = 0;
3886         r->max_spooling                 = 0;
3887         r->session_counter              = session_counter->counter;
3888         r->num_error_out_of_paper       = 0x0;
3889         r->num_error_not_ready          = 0x0;          /* number of print failure */
3890         r->job_error                    = 0x0;
3891         r->number_of_processors         = 0x1;
3892         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3893         r->high_part_total_bytes        = 0x0;
3894
3895         /* ChangeID in milliseconds*/
3896         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3897                                     info2->sharename, &r->change_id);
3898
3899         r->last_error                   = WERR_OK;
3900         r->status                       = nt_printq_status(status.status);
3901         r->enumerate_network_printers   = 0x0;
3902         r->c_setprinter                 = 0x0;
3903         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3904         r->processor_level              = 0x6;          /* 6  ???*/
3905         r->ref_ic                       = 0;
3906         r->reserved2                    = 0;
3907         r->reserved3                    = 0;
3908
3909         return WERR_OK;
3910 }
3911
3912
3913 /********************************************************************
3914  * construct_printer_info1
3915  * fill a spoolss_PrinterInfo1 struct
3916 ********************************************************************/
3917
3918 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3919                                       const struct spoolss_PrinterInfo2 *info2,
3920                                       uint32_t flags,
3921                                       const char *servername,
3922                                       struct spoolss_PrinterInfo1 *r,
3923                                       int snum)
3924 {
3925         WERROR result;
3926
3927         r->flags                = flags;
3928
3929         if (info2->comment == NULL || info2->comment[0] == '\0') {
3930                 r->comment      = lp_comment(mem_ctx, snum);
3931         } else {
3932                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3933         }
3934         W_ERROR_HAVE_NO_MEMORY(r->comment);
3935
3936         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3937         if (!W_ERROR_IS_OK(result)) {
3938                 return result;
3939         }
3940
3941         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3942                                                   r->name,
3943                                                   info2->drivername,
3944                                                   r->comment);
3945         W_ERROR_HAVE_NO_MEMORY(r->description);
3946
3947         return WERR_OK;
3948 }
3949
3950 /********************************************************************
3951  * construct_printer_info2
3952  * fill a spoolss_PrinterInfo2 struct
3953 ********************************************************************/
3954
3955 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3956                                       struct messaging_context *msg_ctx,
3957                                       const struct spoolss_PrinterInfo2 *info2,
3958                                       const char *servername,
3959                                       struct spoolss_PrinterInfo2 *r,
3960                                       int snum)
3961 {
3962         int count;
3963         print_status_struct status;
3964         WERROR result;
3965
3966         count = print_queue_length(msg_ctx, snum, &status);
3967
3968         if (servername) {
3969                 r->servername           = talloc_strdup(mem_ctx, servername);
3970                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3971         } else {
3972                 r->servername           = NULL;
3973         }
3974
3975         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3976         if (!W_ERROR_IS_OK(result)) {
3977                 return result;
3978         }
3979
3980         r->sharename            = lp_servicename(mem_ctx, snum);
3981         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3982         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3983         W_ERROR_HAVE_NO_MEMORY(r->portname);
3984         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3985         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3986
3987         if (info2->comment[0] == '\0') {
3988                 r->comment      = lp_comment(mem_ctx, snum);
3989         } else {
3990                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3991         }
3992         W_ERROR_HAVE_NO_MEMORY(r->comment);
3993
3994         r->location     = talloc_strdup(mem_ctx, info2->location);
3995         if (info2->location[0] == '\0') {
3996                 const char *loc = NULL;
3997                 NTSTATUS nt_status;
3998
3999                 nt_status = printer_list_get_printer(mem_ctx,
4000                                                      info2->sharename,
4001                                                      NULL,
4002                                                      &loc,
4003                                                      NULL);
4004                 if (NT_STATUS_IS_OK(nt_status)) {
4005                         if (loc != NULL) {
4006                                 r->location = talloc_strdup(mem_ctx, loc);
4007                         }
4008                 }
4009         }
4010         W_ERROR_HAVE_NO_MEMORY(r->location);
4011
4012         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4013         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4014         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4015         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4016         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4017         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4018         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4019         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4020
4021         r->attributes           = info2->attributes;
4022
4023         r->priority             = info2->priority;
4024         r->defaultpriority      = info2->defaultpriority;
4025         r->starttime            = info2->starttime;
4026         r->untiltime            = info2->untiltime;
4027         r->status               = nt_printq_status(status.status);
4028         r->cjobs                = count;
4029         r->averageppm           = info2->averageppm;
4030
4031         if (info2->devmode != NULL) {
4032                 result = copy_devicemode(mem_ctx,
4033                                          info2->devmode,
4034                                          &r->devmode);
4035                 if (!W_ERROR_IS_OK(result)) {
4036                         return result;
4037                 }
4038         } else if (lp_default_devmode(snum)) {
4039                 result = spoolss_create_default_devmode(mem_ctx,
4040                                                         info2->printername,
4041                                                         &r->devmode);
4042                 if (!W_ERROR_IS_OK(result)) {
4043                         return result;
4044                 }
4045         } else {
4046                 r->devmode = NULL;
4047                 DEBUG(8,("Returning NULL Devicemode!\n"));
4048         }
4049
4050         compose_devicemode_devicename(r->devmode, r->printername);
4051
4052         r->secdesc = NULL;
4053
4054         if (info2->secdesc != NULL) {
4055                 /* don't use talloc_steal() here unless you do a deep steal of all
4056                    the SEC_DESC members */
4057
4058                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4059         }
4060
4061         return WERR_OK;
4062 }
4063
4064 /********************************************************************
4065  * construct_printer_info3
4066  * fill a spoolss_PrinterInfo3 struct
4067  ********************************************************************/
4068
4069 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4070                                       const struct spoolss_PrinterInfo2 *info2,
4071                                       const char *servername,
4072                                       struct spoolss_PrinterInfo3 *r,
4073                                       int snum)
4074 {
4075         /* These are the components of the SD we are returning. */
4076
4077         if (info2->secdesc != NULL) {
4078                 /* don't use talloc_steal() here unless you do a deep steal of all
4079                    the SEC_DESC members */
4080
4081                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4082                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4083         }
4084
4085         return WERR_OK;
4086 }
4087
4088 /********************************************************************
4089  * construct_printer_info4
4090  * fill a spoolss_PrinterInfo4 struct
4091  ********************************************************************/
4092
4093 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4094                                       const struct spoolss_PrinterInfo2 *info2,
4095                                       const char *servername,
4096                                       struct spoolss_PrinterInfo4 *r,
4097                                       int snum)
4098 {
4099         WERROR result;
4100
4101         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4102         if (!W_ERROR_IS_OK(result)) {
4103                 return result;
4104         }
4105
4106         if (servername) {
4107                 r->servername   = talloc_strdup(mem_ctx, servername);
4108                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4109         } else {
4110                 r->servername = NULL;
4111         }
4112
4113         r->attributes   = info2->attributes;
4114
4115         return WERR_OK;
4116 }
4117
4118 /********************************************************************
4119  * construct_printer_info5
4120  * fill a spoolss_PrinterInfo5 struct
4121  ********************************************************************/
4122
4123 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4124                                       const struct spoolss_PrinterInfo2 *info2,
4125                                       const char *servername,
4126                                       struct spoolss_PrinterInfo5 *r,
4127                                       int snum)
4128 {
4129         WERROR result;
4130
4131         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4132         if (!W_ERROR_IS_OK(result)) {
4133                 return result;
4134         }
4135
4136         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4137         W_ERROR_HAVE_NO_MEMORY(r->portname);
4138
4139         r->attributes   = info2->attributes;
4140
4141         /* these two are not used by NT+ according to MSDN */
4142         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4143         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4144
4145         return WERR_OK;
4146 }
4147
4148 /********************************************************************
4149  * construct_printer_info_6
4150  * fill a spoolss_PrinterInfo6 struct
4151  ********************************************************************/
4152
4153 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4154                                       struct messaging_context *msg_ctx,
4155                                       const struct spoolss_PrinterInfo2 *info2,
4156                                       const char *servername,
4157                                       struct spoolss_PrinterInfo6 *r,
4158                                       int snum)
4159 {
4160         print_status_struct status;
4161
4162         print_queue_length(msg_ctx, snum, &status);
4163
4164         r->status = nt_printq_status(status.status);
4165
4166         return WERR_OK;
4167 }
4168
4169 /********************************************************************
4170  * construct_printer_info7
4171  * fill a spoolss_PrinterInfo7 struct
4172  ********************************************************************/
4173
4174 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4175                                       struct messaging_context *msg_ctx,
4176                                       const char *servername,
4177                                       struct spoolss_PrinterInfo7 *r,
4178                                       int snum)
4179 {
4180         const struct auth_session_info *session_info = get_session_info_system();
4181         struct GUID guid;
4182
4183         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4184                                  servername,
4185                                  lp_servicename(talloc_tos(), snum), &guid, NULL)) {
4186                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4187                 r->action = DSPRINT_PUBLISH;
4188         } else {
4189                 r->guid = talloc_strdup(mem_ctx, "");
4190                 r->action = DSPRINT_UNPUBLISH;
4191         }
4192         W_ERROR_HAVE_NO_MEMORY(r->guid);
4193
4194         return WERR_OK;
4195 }
4196
4197 /********************************************************************
4198  * construct_printer_info8
4199  * fill a spoolss_PrinterInfo8 struct
4200  ********************************************************************/
4201
4202 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4203                                       const struct spoolss_PrinterInfo2 *info2,
4204                                       const char *servername,
4205                                       struct spoolss_DeviceModeInfo *r,
4206                                       int snum)
4207 {
4208         WERROR result;
4209         const char *printername;
4210
4211         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4212         if (!W_ERROR_IS_OK(result)) {
4213                 return result;
4214         }
4215
4216         if (info2->devmode != NULL) {
4217                 result = copy_devicemode(mem_ctx,
4218                                          info2->devmode,
4219                                          &r->devmode);
4220                 if (!W_ERROR_IS_OK(result)) {
4221                         return result;
4222                 }
4223         } else if (lp_default_devmode(snum)) {
4224                 result = spoolss_create_default_devmode(mem_ctx,
4225                                                         info2->printername,
4226                                                         &r->devmode);
4227                 if (!W_ERROR_IS_OK(result)) {
4228                         return result;
4229                 }
4230         } else {
4231                 r->devmode = NULL;
4232                 DEBUG(8,("Returning NULL Devicemode!\n"));
4233         }
4234
4235         compose_devicemode_devicename(r->devmode, printername);
4236
4237         return WERR_OK;
4238 }
4239
4240
4241 /********************************************************************
4242 ********************************************************************/
4243
4244 static bool snum_is_shared_printer(int snum)
4245 {
4246         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4247 }
4248
4249 /********************************************************************
4250  Spoolss_enumprinters.
4251 ********************************************************************/
4252
4253 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4254                                            const struct auth_session_info *session_info,
4255                                            struct messaging_context *msg_ctx,
4256                                            const char *servername,
4257                                            uint32_t level,
4258                                            uint32_t flags,
4259                                            union spoolss_PrinterInfo **info_p,
4260                                            uint32_t *count_p)
4261 {
4262         int snum;
4263         int n_services = lp_numservices();
4264         union spoolss_PrinterInfo *info = NULL;
4265         uint32_t count = 0;
4266         WERROR result = WERR_OK;
4267         struct dcerpc_binding_handle *b = NULL;
4268         TALLOC_CTX *tmp_ctx = NULL;
4269
4270         tmp_ctx = talloc_new(mem_ctx);
4271         if (!tmp_ctx) {
4272                 return WERR_NOMEM;
4273         }
4274
4275         *count_p = 0;
4276         *info_p = NULL;
4277
4278         for (snum = 0; snum < n_services; snum++) {
4279
4280                 const char *printer;
4281                 struct spoolss_PrinterInfo2 *info2;
4282
4283                 if (!snum_is_shared_printer(snum)) {
4284                         continue;
4285                 }
4286
4287                 printer = lp_const_servicename(snum);
4288
4289                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4290                         printer, snum));
4291
4292                 if (b == NULL) {
4293                         result = winreg_printer_binding_handle(tmp_ctx,
4294                                                                session_info,
4295                                                                msg_ctx,
4296                                                                &b);
4297                         if (!W_ERROR_IS_OK(result)) {
4298                                 goto out;
4299                         }
4300                 }
4301
4302                 result = winreg_create_printer(tmp_ctx, b,
4303                                                printer);
4304                 if (!W_ERROR_IS_OK(result)) {
4305                         goto out;
4306                 }
4307
4308                 info = talloc_realloc(tmp_ctx, info,
4309                                             union spoolss_PrinterInfo,
4310                                             count + 1);
4311                 if (!info) {
4312                         result = WERR_NOMEM;
4313                         goto out;
4314                 }
4315
4316                 result = winreg_get_printer(tmp_ctx, b,
4317                                             printer, &info2);
4318                 if (!W_ERROR_IS_OK(result)) {
4319                         goto out;
4320                 }
4321
4322                 switch (level) {
4323                 case 0:
4324                         result = construct_printer_info0(info, session_info,
4325                                                          msg_ctx, info2,
4326                                                          servername,
4327                                                          &info[count].info0, snum);
4328                         break;
4329                 case 1:
4330                         result = construct_printer_info1(info, info2, flags,
4331                                                          servername,
4332                                                          &info[count].info1, snum);
4333                         break;
4334                 case 2:
4335                         result = construct_printer_info2(info, msg_ctx, info2,
4336                                                          servername,
4337                                                          &info[count].info2, snum);
4338                         break;
4339                 case 4:
4340                         result = construct_printer_info4(info, info2,
4341                                                          servername,
4342                                                          &info[count].info4, snum);
4343                         break;
4344                 case 5:
4345                         result = construct_printer_info5(info, info2,
4346                                                          servername,
4347                                                          &info[count].info5, snum);
4348                         break;
4349
4350                 default:
4351                         result = WERR_UNKNOWN_LEVEL;
4352                         goto out;
4353                 }
4354
4355                 if (!W_ERROR_IS_OK(result)) {
4356                         goto out;
4357                 }
4358
4359                 count++;
4360         }
4361
4362 out:
4363         if (W_ERROR_IS_OK(result)) {
4364                 *info_p = talloc_move(mem_ctx, &info);
4365                 *count_p = count;
4366         }
4367
4368         talloc_free(tmp_ctx);
4369
4370         return result;
4371 }
4372
4373 /********************************************************************
4374  * handle enumeration of printers at level 0
4375  ********************************************************************/
4376
4377 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4378                                   const struct auth_session_info *session_info,
4379                                   struct messaging_context *msg_ctx,
4380                                   uint32_t flags,
4381                                   const char *servername,
4382                                   union spoolss_PrinterInfo **info,
4383                                   uint32_t *count)
4384 {
4385         DEBUG(4,("enum_all_printers_info_0\n"));
4386
4387         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4388                                             servername, 0, flags, info, count);
4389 }
4390
4391
4392 /********************************************************************
4393 ********************************************************************/
4394
4395 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4396                                        const struct auth_session_info *session_info,
4397                                        struct messaging_context *msg_ctx,
4398                                        const char *servername,
4399                                        uint32_t flags,
4400                                        union spoolss_PrinterInfo **info,
4401                                        uint32_t *count)
4402 {
4403         DEBUG(4,("enum_all_printers_info_1\n"));
4404
4405         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4406                                             servername, 1, flags, info, count);
4407 }
4408
4409 /********************************************************************
4410  enum_all_printers_info_1_local.
4411 *********************************************************************/
4412
4413 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4414                                              const struct auth_session_info *session_info,
4415                                              struct messaging_context *msg_ctx,
4416                                              const char *servername,
4417                                              union spoolss_PrinterInfo **info,
4418                                              uint32_t *count)
4419 {
4420         DEBUG(4,("enum_all_printers_info_1_local\n"));
4421
4422         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4423                                         servername, PRINTER_ENUM_ICON8, info, count);
4424 }
4425
4426 /********************************************************************
4427  enum_all_printers_info_1_name.
4428 *********************************************************************/
4429
4430 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4431                                             const struct auth_session_info *session_info,
4432                                             struct messaging_context *msg_ctx,
4433                                             const char *servername,
4434                                             union spoolss_PrinterInfo **info,
4435                                             uint32_t *count)
4436 {
4437         const char *s = servername;
4438
4439         DEBUG(4,("enum_all_printers_info_1_name\n"));
4440
4441         if (servername != NULL &&
4442             (servername[0] == '\\') && (servername[1] == '\\')) {
4443                 s = servername + 2;
4444         }
4445
4446         if (!is_myname_or_ipaddr(s)) {
4447                 return WERR_INVALID_NAME;
4448         }
4449
4450         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4451                                         servername, PRINTER_ENUM_ICON8, info, count);
4452 }
4453
4454 /********************************************************************
4455  enum_all_printers_info_1_network.
4456 *********************************************************************/
4457
4458 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4459                                                const struct auth_session_info *session_info,
4460                                                struct messaging_context *msg_ctx,
4461                                                const char *servername,
4462                                                union spoolss_PrinterInfo **info,
4463                                                uint32_t *count)
4464 {
4465         const char *s = servername;
4466
4467         DEBUG(4,("enum_all_printers_info_1_network\n"));
4468
4469         /* If we respond to a enum_printers level 1 on our name with flags
4470            set to PRINTER_ENUM_REMOTE with a list of printers then these
4471            printers incorrectly appear in the APW browse list.
4472            Specifically the printers for the server appear at the workgroup
4473            level where all the other servers in the domain are
4474            listed. Windows responds to this call with a
4475            WERR_CAN_NOT_COMPLETE so we should do the same. */
4476
4477         if (servername != NULL &&
4478             (servername[0] == '\\') && (servername[1] == '\\')) {
4479                  s = servername + 2;
4480         }
4481
4482         if (is_myname_or_ipaddr(s)) {
4483                  return WERR_CAN_NOT_COMPLETE;
4484         }
4485
4486         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4487                                         servername, PRINTER_ENUM_NAME, info, count);
4488 }
4489
4490 /********************************************************************
4491  * api_spoolss_enumprinters
4492  *
4493  * called from api_spoolss_enumprinters (see this to understand)
4494  ********************************************************************/
4495
4496 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4497                                        const struct auth_session_info *session_info,
4498                                        struct messaging_context *msg_ctx,
4499                                        const char *servername,
4500                                        union spoolss_PrinterInfo **info,
4501                                        uint32_t *count)
4502 {
4503         DEBUG(4,("enum_all_printers_info_2\n"));
4504
4505         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4506                                             servername, 2, 0, info, count);
4507 }
4508
4509 /********************************************************************
4510  * handle enumeration of printers at level 1
4511  ********************************************************************/
4512
4513 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4514                                   const struct auth_session_info *session_info,
4515                                   struct messaging_context *msg_ctx,
4516                                   uint32_t flags,
4517                                   const char *servername,
4518                                   union spoolss_PrinterInfo **info,
4519                                   uint32_t *count)
4520 {
4521         /* Not all the flags are equals */
4522
4523         if (flags & PRINTER_ENUM_LOCAL) {
4524                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4525                                                       msg_ctx, servername, info, count);
4526         }
4527
4528         if (flags & PRINTER_ENUM_NAME) {
4529                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4530                                                      msg_ctx, servername, info,
4531                                                      count);
4532         }
4533
4534         if (flags & PRINTER_ENUM_NETWORK) {
4535                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4536                                                         msg_ctx, servername, info,
4537                                                         count);
4538         }
4539
4540         return WERR_OK; /* NT4sp5 does that */
4541 }
4542
4543 /********************************************************************
4544  * handle enumeration of printers at level 2
4545  ********************************************************************/
4546
4547 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4548                                   const struct auth_session_info *session_info,
4549                                   struct messaging_context *msg_ctx,
4550                                   uint32_t flags,
4551                                   const char *servername,
4552                                   union spoolss_PrinterInfo **info,
4553                                   uint32_t *count)
4554 {
4555         if (flags & PRINTER_ENUM_LOCAL) {
4556
4557                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4558                                                 servername,
4559                                                 info, count);
4560         }
4561
4562         if (flags & PRINTER_ENUM_NAME) {
4563                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4564                         return WERR_INVALID_NAME;
4565                 }
4566
4567                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4568                                                 servername,
4569                                                 info, count);
4570         }
4571
4572         if (flags & PRINTER_ENUM_REMOTE) {
4573                 return WERR_UNKNOWN_LEVEL;
4574         }
4575
4576         return WERR_OK;
4577 }
4578
4579 /********************************************************************
4580  * handle enumeration of printers at level 4
4581  ********************************************************************/
4582
4583 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4584                                   const struct auth_session_info *session_info,
4585                                   struct messaging_context *msg_ctx,
4586                                   uint32_t flags,
4587                                   const char *servername,
4588                                   union spoolss_PrinterInfo **info,
4589                                   uint32_t *count)
4590 {
4591         DEBUG(4,("enum_all_printers_info_4\n"));
4592
4593         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4594                                             servername, 4, flags, info, count);
4595 }
4596
4597
4598 /********************************************************************
4599  * handle enumeration of printers at level 5
4600  ********************************************************************/
4601
4602 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4603                                   const struct auth_session_info *session_info,
4604                                   struct messaging_context *msg_ctx,
4605                                   uint32_t flags,
4606                                   const char *servername,
4607                                   union spoolss_PrinterInfo **info,
4608                                   uint32_t *count)
4609 {
4610         DEBUG(4,("enum_all_printers_info_5\n"));
4611
4612         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4613                                             servername, 5, flags, info, count);
4614 }
4615
4616 /****************************************************************
4617  _spoolss_EnumPrinters
4618 ****************************************************************/
4619
4620 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4621                              struct spoolss_EnumPrinters *r)
4622 {
4623         const struct auth_session_info *session_info = get_session_info_system();
4624         WERROR result;
4625
4626         /* that's an [in out] buffer */
4627
4628         if (!r->in.buffer && (r->in.offered != 0)) {
4629                 return WERR_INVALID_PARAM;
4630         }
4631
4632         DEBUG(4,("_spoolss_EnumPrinters\n"));
4633
4634         *r->out.needed = 0;
4635         *r->out.count = 0;
4636         *r->out.info = NULL;
4637
4638         /*
4639          * Level 1:
4640          *          flags==PRINTER_ENUM_NAME
4641          *           if name=="" then enumerates all printers
4642          *           if name!="" then enumerate the printer
4643          *          flags==PRINTER_ENUM_REMOTE
4644          *          name is NULL, enumerate printers
4645          * Level 2: name!="" enumerates printers, name can't be NULL
4646          * Level 3: doesn't exist
4647          * Level 4: does a local registry lookup
4648          * Level 5: same as Level 2
4649          */
4650
4651         if (r->in.server && r->in.server[0] == '\0') {
4652                 r->in.server = NULL;
4653         }
4654
4655         switch (r->in.level) {
4656         case 0:
4657                 result = enumprinters_level0(p->mem_ctx, session_info,
4658                                              p->msg_ctx, r->in.flags,
4659                                              r->in.server,
4660                                              r->out.info, r->out.count);
4661                 break;
4662         case 1:
4663                 result = enumprinters_level1(p->mem_ctx, session_info,
4664                                              p->msg_ctx, r->in.flags,
4665                                              r->in.server,
4666                                              r->out.info, r->out.count);
4667                 break;
4668         case 2:
4669                 result = enumprinters_level2(p->mem_ctx, session_info,
4670                                              p->msg_ctx, r->in.flags,
4671                                              r->in.server,
4672                                              r->out.info, r->out.count);
4673                 break;
4674         case 4:
4675                 result = enumprinters_level4(p->mem_ctx, session_info,
4676                                              p->msg_ctx, r->in.flags,
4677                                              r->in.server,
4678                                              r->out.info, r->out.count);
4679                 break;
4680         case 5:
4681                 result = enumprinters_level5(p->mem_ctx, session_info,
4682                                              p->msg_ctx, r->in.flags,
4683                                              r->in.server,
4684                                              r->out.info, r->out.count);
4685                 break;
4686         default:
4687                 return WERR_UNKNOWN_LEVEL;
4688         }
4689
4690         if (!W_ERROR_IS_OK(result)) {
4691                 return result;
4692         }
4693
4694         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4695                                                      spoolss_EnumPrinters,
4696                                                      *r->out.info, r->in.level,
4697                                                      *r->out.count);
4698         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4699         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4700
4701         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4702 }
4703
4704 /****************************************************************
4705  _spoolss_GetPrinter
4706 ****************************************************************/
4707
4708 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4709                            struct spoolss_GetPrinter *r)
4710 {
4711         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4712         struct spoolss_PrinterInfo2 *info2 = NULL;
4713         WERROR result = WERR_OK;
4714         int snum;
4715
4716         /* that's an [in out] buffer */
4717
4718         if (!r->in.buffer && (r->in.offered != 0)) {
4719                 return WERR_INVALID_PARAM;
4720         }
4721
4722         *r->out.needed = 0;
4723
4724         if (Printer == NULL) {
4725                 return WERR_BADFID;
4726         }
4727
4728         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4729                 return WERR_BADFID;
4730         }
4731
4732         result = winreg_get_printer_internal(p->mem_ctx,
4733                                     get_session_info_system(),
4734                                     p->msg_ctx,
4735                                     lp_const_servicename(snum),
4736                                     &info2);
4737         if (!W_ERROR_IS_OK(result)) {
4738                 goto out;
4739         }
4740
4741         switch (r->in.level) {
4742         case 0:
4743                 result = construct_printer_info0(p->mem_ctx,
4744                                                  get_session_info_system(),
4745                                                  p->msg_ctx,
4746                                                  info2,
4747                                                  Printer->servername,
4748                                                  &r->out.info->info0,
4749                                                  snum);
4750                 break;
4751         case 1:
4752                 result = construct_printer_info1(p->mem_ctx, info2,
4753                                                  PRINTER_ENUM_ICON8,
4754                                                  Printer->servername,
4755                                                  &r->out.info->info1, snum);
4756                 break;
4757         case 2:
4758                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4759                                                  Printer->servername,
4760                                                  &r->out.info->info2, snum);
4761                 break;
4762         case 3:
4763                 result = construct_printer_info3(p->mem_ctx, info2,
4764                                                  Printer->servername,
4765                                                  &r->out.info->info3, snum);
4766                 break;
4767         case 4:
4768                 result = construct_printer_info4(p->mem_ctx, info2,
4769                                                  Printer->servername,
4770                                                  &r->out.info->info4, snum);
4771                 break;
4772         case 5:
4773                 result = construct_printer_info5(p->mem_ctx, info2,
4774                                                  Printer->servername,
4775                                                  &r->out.info->info5, snum);
4776                 break;
4777         case 6:
4778                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4779                                                  Printer->servername,
4780                                                  &r->out.info->info6, snum);
4781                 break;
4782         case 7:
4783                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4784                                                  Printer->servername,
4785                                                  &r->out.info->info7, snum);
4786                 break;
4787         case 8:
4788                 result = construct_printer_info8(p->mem_ctx, info2,
4789                                                  Printer->servername,
4790                                                  &r->out.info->info8, snum);
4791                 break;
4792         default:
4793                 result = WERR_UNKNOWN_LEVEL;
4794                 break;
4795         }
4796         TALLOC_FREE(info2);
4797
4798  out:
4799         if (!W_ERROR_IS_OK(result)) {
4800                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4801                           r->in.level, win_errstr(result)));
4802                 TALLOC_FREE(r->out.info);
4803                 return result;
4804         }
4805
4806         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4807                                                r->out.info, r->in.level);
4808         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4809
4810         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4811 }
4812
4813 /********************************************************************
4814  ********************************************************************/
4815
4816 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4817         do { \
4818                 if (in && strlen(in)) { \
4819                         out = talloc_strdup(mem_ctx, in); \
4820                 } else { \
4821                         out = talloc_strdup(mem_ctx, ""); \
4822                 } \
4823                 W_ERROR_HAVE_NO_MEMORY(out); \
4824         } while (0);
4825
4826 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4827         do { \
4828                 if (in && strlen(in)) { \
4829                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4830                 } else { \
4831                         out = talloc_strdup(mem_ctx, ""); \
4832                 } \
4833                 W_ERROR_HAVE_NO_MEMORY(out); \
4834         } while (0);
4835
4836 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4837                                                   const char **string_array,
4838                                                   const char ***presult,
4839                                                   const char *cservername,
4840                                                   const char *arch,
4841                                                   int version)
4842 {
4843         int i, num_strings = 0;
4844         const char **array = NULL;
4845
4846         if (string_array == NULL) {
4847                 return WERR_INVALID_PARAMETER;
4848         }
4849
4850         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4851                 const char *str = NULL;
4852
4853                 if (cservername == NULL || arch == NULL) {
4854                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4855                 } else {
4856                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4857                 }
4858
4859                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4860                         TALLOC_FREE(array);
4861                         return WERR_NOMEM;
4862                 }
4863         }
4864
4865         if (i > 0) {
4866                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4867                              &array, &num_strings);
4868         }
4869
4870         if (presult) {
4871                 *presult = array;
4872         }
4873
4874         return WERR_OK;
4875 }
4876
4877 /********************************************************************
4878  * fill a spoolss_DriverInfo1 struct
4879  ********************************************************************/
4880
4881 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4882                                         struct spoolss_DriverInfo1 *r,
4883                                         const struct spoolss_DriverInfo8 *driver,
4884                                         const char *servername)
4885 {
4886         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4887         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4888
4889         return WERR_OK;
4890 }
4891
4892 /********************************************************************
4893  * fill a spoolss_DriverInfo2 struct
4894  ********************************************************************/
4895
4896 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4897                                         struct spoolss_DriverInfo2 *r,
4898                                         const struct spoolss_DriverInfo8 *driver,
4899                                         const char *servername)
4900
4901 {
4902         const char *cservername = canon_servername(servername);
4903
4904         r->version              = driver->version;
4905
4906         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4907         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4908         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4909         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4910
4911         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4912                                driver->architecture,
4913                                driver->version,
4914                                driver->driver_path,
4915                                r->driver_path);
4916
4917         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4918                                driver->architecture,
4919                                driver->version,
4920                                driver->data_file,
4921                                r->data_file);
4922
4923         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4924                                driver->architecture,
4925                                driver->version,
4926                                driver->config_file,
4927                                r->config_file);
4928
4929         return WERR_OK;
4930 }
4931
4932 /********************************************************************
4933  * fill a spoolss_DriverInfo3 struct
4934  ********************************************************************/
4935
4936 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4937                                         struct spoolss_DriverInfo3 *r,
4938                                         const struct spoolss_DriverInfo8 *driver,
4939                                         const char *servername)
4940 {
4941         const char *cservername = canon_servername(servername);
4942
4943         r->version              = driver->version;
4944
4945         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4946         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4947         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4948         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4949
4950         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4951                                driver->architecture,
4952                                driver->version,
4953                                driver->driver_path,
4954                                r->driver_path);
4955
4956         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4957                                driver->architecture,
4958                                driver->version,
4959                                driver->data_file,
4960                                r->data_file);
4961
4962         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4963                                driver->architecture,
4964                                driver->version,
4965                                driver->config_file,
4966                                r->config_file);
4967
4968         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4969                                driver->architecture,
4970                                driver->version,
4971                                driver->help_file,
4972                                r->help_file);
4973
4974         FILL_DRIVER_STRING(mem_ctx,
4975                            driver->monitor_name,
4976                            r->monitor_name);
4977
4978         FILL_DRIVER_STRING(mem_ctx,
4979                            driver->default_datatype,
4980                            r->default_datatype);
4981
4982         return string_array_from_driver_info(mem_ctx,
4983                                              driver->dependent_files,
4984                                              &r->dependent_files,
4985                                              cservername,
4986                                              driver->architecture,
4987                                              driver->version);
4988 }
4989
4990 /********************************************************************
4991  * fill a spoolss_DriverInfo4 struct
4992  ********************************************************************/
4993
4994 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4995                                         struct spoolss_DriverInfo4 *r,
4996                                         const struct spoolss_DriverInfo8 *driver,
4997                                         const char *servername)
4998 {
4999         const char *cservername = canon_servername(servername);
5000         WERROR result;
5001
5002         r->version              = driver->version;
5003
5004         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5005         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5006         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5007         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5008
5009         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5010                                driver->architecture,
5011                                driver->version,
5012                                driver->driver_path,
5013                                r->driver_path);
5014
5015         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5016                                driver->architecture,
5017                                driver->version,
5018                                driver->data_file,
5019                                r->data_file);
5020
5021         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5022                                driver->architecture,
5023                                driver->version,
5024                                driver->config_file,
5025                                r->config_file);
5026
5027         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5028                                driver->architecture,
5029                                driver->version,
5030                                driver->help_file,
5031                                r->help_file);
5032
5033         result = string_array_from_driver_info(mem_ctx,
5034                                                driver->dependent_files,
5035                                                &r->dependent_files,
5036                                                cservername,
5037                                                driver->architecture,
5038                                                driver->version);
5039         if (!W_ERROR_IS_OK(result)) {
5040                 return result;
5041         }
5042
5043         FILL_DRIVER_STRING(mem_ctx,
5044                            driver->monitor_name,
5045                            r->monitor_name);
5046
5047         FILL_DRIVER_STRING(mem_ctx,
5048                            driver->default_datatype,
5049                            r->default_datatype);
5050
5051
5052         result = string_array_from_driver_info(mem_ctx,
5053                                                driver->previous_names,
5054                                                &r->previous_names,
5055                                                NULL, NULL, 0);
5056
5057         return result;
5058 }
5059
5060 /********************************************************************
5061  * fill a spoolss_DriverInfo5 struct
5062  ********************************************************************/
5063
5064 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5065                                         struct spoolss_DriverInfo5 *r,
5066                                         const struct spoolss_DriverInfo8 *driver,
5067                                         const char *servername)
5068 {
5069         const char *cservername = canon_servername(servername);
5070
5071         r->version              = driver->version;
5072
5073         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5074         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5075         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5076         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5077
5078         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5079                                driver->architecture,
5080                                driver->version,
5081                                driver->driver_path,
5082                                r->driver_path);
5083
5084         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5085                                driver->architecture,
5086                                driver->version,
5087                                driver->data_file,
5088                                r->data_file);
5089
5090         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5091                                driver->architecture,
5092                                driver->version,
5093                                driver->config_file,
5094                                r->config_file);
5095
5096         r->driver_attributes    = 0;
5097         r->config_version       = 0;
5098         r->driver_version       = 0;
5099
5100         return WERR_OK;
5101 }
5102 /********************************************************************
5103  * fill a spoolss_DriverInfo6 struct
5104  ********************************************************************/
5105
5106 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5107                                         struct spoolss_DriverInfo6 *r,
5108                                         const struct spoolss_DriverInfo8 *driver,
5109                                         const char *servername)
5110 {
5111         const char *cservername = canon_servername(servername);
5112         WERROR result;
5113
5114         r->version              = driver->version;
5115
5116         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5117         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5118         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5119         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5120
5121         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5122                                driver->architecture,
5123                                driver->version,
5124                                driver->driver_path,
5125                                r->driver_path);
5126
5127         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5128                                driver->architecture,
5129                                driver->version,
5130                                driver->data_file,
5131                                r->data_file);
5132
5133         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5134                                driver->architecture,
5135                                driver->version,
5136                                driver->config_file,
5137                                r->config_file);
5138
5139         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5140                                driver->architecture,
5141                                driver->version,
5142                                driver->help_file,
5143                                r->help_file);
5144
5145         FILL_DRIVER_STRING(mem_ctx,
5146                            driver->monitor_name,
5147                            r->monitor_name);
5148
5149         FILL_DRIVER_STRING(mem_ctx,
5150                            driver->default_datatype,
5151                            r->default_datatype);
5152
5153         result = string_array_from_driver_info(mem_ctx,
5154                                                driver->dependent_files,
5155                                                &r->dependent_files,
5156                                                cservername,
5157                                                driver->architecture,
5158                                                driver->version);
5159         if (!W_ERROR_IS_OK(result)) {
5160                 return result;
5161         }
5162
5163         result = string_array_from_driver_info(mem_ctx,
5164                                                driver->previous_names,
5165                                                &r->previous_names,
5166                                                NULL, NULL, 0);
5167         if (!W_ERROR_IS_OK(result)) {
5168                 return result;
5169         }
5170
5171         r->driver_date          = driver->driver_date;
5172         r->driver_version       = driver->driver_version;
5173
5174         FILL_DRIVER_STRING(mem_ctx,
5175                            driver->manufacturer_name,
5176                            r->manufacturer_name);
5177         FILL_DRIVER_STRING(mem_ctx,
5178                            driver->manufacturer_url,
5179                            r->manufacturer_url);
5180         FILL_DRIVER_STRING(mem_ctx,
5181                            driver->hardware_id,
5182                            r->hardware_id);
5183         FILL_DRIVER_STRING(mem_ctx,
5184                            driver->provider,
5185                            r->provider);
5186
5187         return WERR_OK;
5188 }
5189
5190 /********************************************************************
5191  * fill a spoolss_DriverInfo8 struct
5192  ********************************************************************/
5193
5194 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5195                                         struct spoolss_DriverInfo8 *r,
5196                                         const struct spoolss_DriverInfo8 *driver,
5197                                         const char *servername)
5198 {
5199         const char *cservername = canon_servername(servername);
5200         WERROR result;
5201
5202         r->version              = driver->version;
5203
5204         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5205         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5206         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5207         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5208
5209         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5210                                driver->architecture,
5211                                driver->version,
5212                                driver->driver_path,
5213                                r->driver_path);
5214
5215         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5216                                driver->architecture,
5217                                driver->version,
5218                                driver->data_file,
5219                                r->data_file);
5220
5221         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5222                                driver->architecture,
5223                                driver->version,
5224                                driver->config_file,
5225                                r->config_file);
5226
5227         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5228                                driver->architecture,
5229                                driver->version,
5230                                driver->help_file,
5231                                r->help_file);
5232
5233         FILL_DRIVER_STRING(mem_ctx,
5234                            driver->monitor_name,
5235                            r->monitor_name);
5236
5237         FILL_DRIVER_STRING(mem_ctx,
5238                            driver->default_datatype,
5239                            r->default_datatype);
5240
5241         result = string_array_from_driver_info(mem_ctx,
5242                                                driver->dependent_files,
5243                                                &r->dependent_files,
5244                                                cservername,
5245                                                driver->architecture,
5246                                                driver->version);
5247         if (!W_ERROR_IS_OK(result)) {
5248                 return result;
5249         }
5250
5251         result = string_array_from_driver_info(mem_ctx,
5252                                                driver->previous_names,
5253                                                &r->previous_names,
5254                                                NULL, NULL, 0);
5255         if (!W_ERROR_IS_OK(result)) {
5256                 return result;
5257         }
5258
5259         r->driver_date          = driver->driver_date;
5260         r->driver_version       = driver->driver_version;
5261
5262         FILL_DRIVER_STRING(mem_ctx,
5263                            driver->manufacturer_name,
5264                            r->manufacturer_name);
5265         FILL_DRIVER_STRING(mem_ctx,
5266                            driver->manufacturer_url,
5267                            r->manufacturer_url);
5268         FILL_DRIVER_STRING(mem_ctx,
5269                            driver->hardware_id,
5270                            r->hardware_id);
5271         FILL_DRIVER_STRING(mem_ctx,
5272                            driver->provider,
5273                            r->provider);
5274
5275         FILL_DRIVER_STRING(mem_ctx,
5276                            driver->print_processor,
5277                            r->print_processor);
5278         FILL_DRIVER_STRING(mem_ctx,
5279                            driver->vendor_setup,
5280                            r->vendor_setup);
5281
5282         result = string_array_from_driver_info(mem_ctx,
5283                                                driver->color_profiles,
5284                                                &r->color_profiles,
5285                                                NULL, NULL, 0);
5286         if (!W_ERROR_IS_OK(result)) {
5287                 return result;
5288         }
5289
5290         FILL_DRIVER_STRING(mem_ctx,
5291                            driver->inf_path,
5292                            r->inf_path);
5293
5294         r->printer_driver_attributes    = driver->printer_driver_attributes;
5295
5296         result = string_array_from_driver_info(mem_ctx,
5297                                                driver->core_driver_dependencies,
5298                                                &r->core_driver_dependencies,
5299                                                NULL, NULL, 0);
5300         if (!W_ERROR_IS_OK(result)) {
5301                 return result;
5302         }
5303
5304         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5305         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5306
5307         return WERR_OK;
5308 }
5309
5310 #if 0 /* disabled until marshalling issues are resolved - gd */
5311 /********************************************************************
5312  ********************************************************************/
5313
5314 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5315                                           struct spoolss_DriverFileInfo *r,
5316                                           const char *cservername,
5317                                           const char *file_name,
5318                                           enum spoolss_DriverFileType file_type,
5319                                           uint32_t file_version)
5320 {
5321         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5322                                           cservername, file_name);
5323         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5324         r->file_type    = file_type;
5325         r->file_version = file_version;
5326
5327         return WERR_OK;
5328 }
5329
5330 /********************************************************************
5331  ********************************************************************/
5332
5333 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5334                                                  const struct spoolss_DriverInfo8 *driver,
5335                                                  const char *cservername,
5336                                                  struct spoolss_DriverFileInfo **info_p,
5337                                                  uint32_t *count_p)
5338 {
5339         struct spoolss_DriverFileInfo *info = NULL;
5340         uint32_t count = 0;
5341         WERROR result;
5342         uint32_t i;
5343
5344         *info_p = NULL;
5345         *count_p = 0;
5346
5347         if (strlen(driver->driver_path)) {
5348                 info = talloc_realloc(mem_ctx, info,
5349                                             struct spoolss_DriverFileInfo,
5350                                             count + 1);
5351                 W_ERROR_HAVE_NO_MEMORY(info);
5352                 result = fill_spoolss_DriverFileInfo(info,
5353                                                      &info[count],
5354                                                      cservername,
5355                                                      driver->driver_path,
5356                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5357                                                      0);
5358                 W_ERROR_NOT_OK_RETURN(result);
5359                 count++;
5360         }
5361
5362         if (strlen(driver->config_file)) {
5363                 info = talloc_realloc(mem_ctx, info,
5364                                             struct spoolss_DriverFileInfo,
5365                                             count + 1);
5366                 W_ERROR_HAVE_NO_MEMORY(info);
5367                 result = fill_spoolss_DriverFileInfo(info,
5368                                                      &info[count],
5369                                                      cservername,
5370                                                      driver->config_file,
5371                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5372                                                      0);
5373                 W_ERROR_NOT_OK_RETURN(result);
5374                 count++;
5375         }
5376
5377         if (strlen(driver->data_file)) {
5378                 info = talloc_realloc(mem_ctx, info,
5379                                             struct spoolss_DriverFileInfo,
5380                                             count + 1);
5381                 W_ERROR_HAVE_NO_MEMORY(info);
5382                 result = fill_spoolss_DriverFileInfo(info,
5383                                                      &info[count],
5384                                                      cservername,
5385                                                      driver->data_file,
5386                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5387                                                      0);
5388                 W_ERROR_NOT_OK_RETURN(result);
5389                 count++;
5390         }
5391
5392         if (strlen(driver->help_file)) {
5393                 info = talloc_realloc(mem_ctx, info,
5394                                             struct spoolss_DriverFileInfo,
5395                                             count + 1);
5396                 W_ERROR_HAVE_NO_MEMORY(info);
5397                 result = fill_spoolss_DriverFileInfo(info,
5398                                                      &info[count],
5399                                                      cservername,
5400                                                      driver->help_file,
5401                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5402                                                      0);
5403                 W_ERROR_NOT_OK_RETURN(result);
5404                 count++;
5405         }
5406
5407         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5408                 info = talloc_realloc(mem_ctx, info,
5409                                             struct spoolss_DriverFileInfo,
5410                                             count + 1);
5411                 W_ERROR_HAVE_NO_MEMORY(info);
5412                 result = fill_spoolss_DriverFileInfo(info,
5413                                                      &info[count],
5414                                                      cservername,
5415                                                      driver->dependent_files[i],
5416                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5417                                                      0);
5418                 W_ERROR_NOT_OK_RETURN(result);
5419                 count++;
5420         }
5421
5422         *info_p = info;
5423         *count_p = count;
5424
5425         return WERR_OK;
5426 }
5427
5428 /********************************************************************
5429  * fill a spoolss_DriverInfo101 struct
5430  ********************************************************************/
5431
5432 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5433                                           struct spoolss_DriverInfo101 *r,
5434                                           const struct spoolss_DriverInfo8 *driver,
5435                                           const char *servername)
5436 {
5437         const char *cservername = canon_servername(servername);
5438         WERROR result;
5439
5440         r->version              = driver->version;
5441
5442         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5443         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5444         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5445         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5446
5447         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5448                                                     cservername,
5449                                                     &r->file_info,
5450                                                     &r->file_count);
5451         if (!W_ERROR_IS_OK(result)) {
5452                 return result;
5453         }
5454
5455         FILL_DRIVER_STRING(mem_ctx,
5456                            driver->monitor_name,
5457                            r->monitor_name);
5458
5459         FILL_DRIVER_STRING(mem_ctx,
5460                            driver->default_datatype,
5461                            r->default_datatype);
5462
5463         result = string_array_from_driver_info(mem_ctx,
5464                                                driver->previous_names,
5465                                                &r->previous_names,
5466                                                NULL, NULL, 0);
5467         if (!W_ERROR_IS_OK(result)) {
5468                 return result;
5469         }
5470
5471         r->driver_date          = driver->driver_date;
5472         r->driver_version       = driver->driver_version;
5473
5474         FILL_DRIVER_STRING(mem_ctx,
5475                            driver->manufacturer_name,
5476                            r->manufacturer_name);
5477         FILL_DRIVER_STRING(mem_ctx,
5478                            driver->manufacturer_url,
5479                            r->manufacturer_url);
5480         FILL_DRIVER_STRING(mem_ctx,
5481                            driver->hardware_id,
5482                            r->hardware_id);
5483         FILL_DRIVER_STRING(mem_ctx,
5484                            driver->provider,
5485                            r->provider);
5486
5487         return WERR_OK;
5488 }
5489 #endif
5490 /********************************************************************
5491  ********************************************************************/
5492
5493 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5494                                                   const struct auth_session_info *session_info,
5495                                                   struct messaging_context *msg_ctx,
5496                                                   uint32_t level,
5497                                                   union spoolss_DriverInfo *r,
5498                                                   int snum,
5499                                                   const char *servername,
5500                                                   const char *architecture,
5501                                                   uint32_t version)
5502 {
5503         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5504         struct spoolss_DriverInfo8 *driver;
5505         WERROR result;
5506         struct dcerpc_binding_handle *b;
5507         TALLOC_CTX *tmp_ctx = NULL;
5508
5509         if (level == 101) {
5510                 return WERR_UNKNOWN_LEVEL;
5511         }
5512
5513         tmp_ctx = talloc_new(mem_ctx);
5514         if (!tmp_ctx) {
5515                 return WERR_NOMEM;
5516         }
5517
5518         result = winreg_printer_binding_handle(tmp_ctx,
5519                                                session_info,
5520                                                msg_ctx,
5521                                                &b);
5522         if (!W_ERROR_IS_OK(result)) {
5523                 goto done;
5524         }
5525
5526         result = winreg_get_printer(tmp_ctx, b,
5527                                     lp_const_servicename(snum),
5528                                     &pinfo2);
5529
5530         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5531                 win_errstr(result)));
5532
5533         if (!W_ERROR_IS_OK(result)) {
5534                 result = WERR_INVALID_PRINTER_NAME;
5535                 goto done;
5536         }
5537
5538         result = winreg_get_driver(tmp_ctx, b,
5539                                    architecture,
5540                                    pinfo2->drivername, version, &driver);
5541
5542         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5543                 win_errstr(result)));
5544
5545         if (!W_ERROR_IS_OK(result)) {
5546                 /*
5547                  * Is this a W2k client ?
5548                  */
5549
5550                 if (version < 3) {
5551                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5552                         goto done;
5553                 }
5554
5555                 /* Yes - try again with a WinNT driver. */
5556                 version = 2;
5557                 result = winreg_get_driver(tmp_ctx, b,
5558                                            architecture,
5559                                            pinfo2->drivername,
5560                                            version, &driver);
5561                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5562                         win_errstr(result)));
5563                 if (!W_ERROR_IS_OK(result)) {
5564                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5565                         goto done;
5566                 }
5567         }
5568
5569         /* these are allocated on mem_ctx and not tmp_ctx because they are
5570          * the 'return value' and need to utlive this call */
5571         switch (level) {
5572         case 1:
5573                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5574                 break;
5575         case 2:
5576                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5577                 break;
5578         case 3:
5579                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5580                 break;
5581         case 4:
5582                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5583                 break;
5584         case 5:
5585                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5586                 break;
5587         case 6:
5588                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5589                 break;
5590         case 8:
5591                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5592                 break;
5593 #if 0 /* disabled until marshalling issues are resolved - gd */
5594         case 101:
5595                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5596                 break;
5597 #endif
5598         default:
5599                 result = WERR_UNKNOWN_LEVEL;
5600                 break;
5601         }
5602
5603 done:
5604         talloc_free(tmp_ctx);
5605         return result;
5606 }
5607
5608 /****************************************************************
5609  _spoolss_GetPrinterDriver2
5610 ****************************************************************/
5611
5612 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5613                                   struct spoolss_GetPrinterDriver2 *r)
5614 {
5615         struct printer_handle *printer;
5616         WERROR result;
5617         uint32_t version = r->in.client_major_version;
5618
5619         int snum;
5620
5621         /* that's an [in out] buffer */
5622
5623         if (!r->in.buffer && (r->in.offered != 0)) {
5624                 return WERR_INVALID_PARAM;
5625         }
5626
5627         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5628
5629         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5630                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5631                 return WERR_INVALID_PRINTER_NAME;
5632         }
5633
5634         *r->out.needed = 0;
5635         *r->out.server_major_version = 0;
5636         *r->out.server_minor_version = 0;
5637
5638         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5639                 return WERR_BADFID;
5640         }
5641
5642         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5643                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5644                         "downgrading to v3\n"));
5645                 version = SPOOLSS_DRIVER_VERSION_200X;
5646         }
5647
5648         result = construct_printer_driver_info_level(p->mem_ctx,
5649                                                      get_session_info_system(),
5650                                                      p->msg_ctx,
5651                                                      r->in.level, r->out.info,
5652                                                      snum, printer->servername,
5653                                                      r->in.architecture,
5654                                                      version);
5655         if (!W_ERROR_IS_OK(result)) {
5656                 TALLOC_FREE(r->out.info);
5657                 return result;
5658         }
5659
5660         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5661                                                r->out.info, r->in.level);
5662         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5663
5664         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5665 }
5666
5667
5668 /****************************************************************
5669  _spoolss_StartPagePrinter
5670 ****************************************************************/
5671
5672 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5673                                  struct spoolss_StartPagePrinter *r)
5674 {
5675         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5676
5677         if (!Printer) {
5678                 DEBUG(3,("_spoolss_StartPagePrinter: "
5679                         "Error in startpageprinter printer handle\n"));
5680                 return WERR_BADFID;
5681         }
5682
5683         Printer->page_started = true;
5684         return WERR_OK;
5685 }
5686
5687 /****************************************************************
5688  _spoolss_EndPagePrinter
5689 ****************************************************************/
5690
5691 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5692                                struct spoolss_EndPagePrinter *r)
5693 {
5694         int snum;
5695
5696         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5697
5698         if (!Printer) {
5699                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5700                         OUR_HANDLE(r->in.handle)));
5701                 return WERR_BADFID;
5702         }
5703
5704         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5705                 return WERR_BADFID;
5706
5707         Printer->page_started = false;
5708         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5709
5710         return WERR_OK;
5711 }
5712
5713 /****************************************************************
5714  _spoolss_StartDocPrinter
5715 ****************************************************************/
5716
5717 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5718                                 struct spoolss_StartDocPrinter *r)
5719 {
5720         struct spoolss_DocumentInfo1 *info_1;
5721         int snum;
5722         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5723         WERROR werr;
5724         char *rhost;
5725         int rc;
5726
5727         if (!Printer) {
5728                 DEBUG(2,("_spoolss_StartDocPrinter: "
5729                         "Invalid handle (%s:%u:%u)\n",
5730                         OUR_HANDLE(r->in.handle)));
5731                 return WERR_BADFID;
5732         }
5733
5734         if (Printer->jobid) {
5735                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5736                           "StartDocPrinter called twice! "
5737                           "(existing jobid = %d)\n", Printer->jobid));
5738                 return WERR_INVALID_HANDLE;
5739         }
5740
5741         if (r->in.info_ctr->level != 1) {
5742                 return WERR_UNKNOWN_LEVEL;
5743         }
5744
5745         info_1 = r->in.info_ctr->info.info1;
5746
5747         /*
5748          * a nice thing with NT is it doesn't listen to what you tell it.
5749          * when asked to send _only_ RAW datas, it tries to send datas
5750          * in EMF format.
5751          *
5752          * So I add checks like in NT Server ...
5753          */
5754
5755         if (info_1->datatype) {
5756                 if (strcmp(info_1->datatype, "RAW") != 0) {
5757                         *r->out.job_id = 0;
5758                         return WERR_INVALID_DATATYPE;
5759                 }
5760         }
5761
5762         /* get the share number of the printer */
5763         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5764                 return WERR_BADFID;
5765         }
5766
5767         rc = get_remote_hostname(p->remote_address,
5768                                  &rhost,
5769                                  p->mem_ctx);
5770         if (rc < 0) {
5771                 return WERR_NOMEM;
5772         }
5773         if (strequal(rhost,"UNKNOWN")) {
5774                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5775                                                          p->mem_ctx);
5776                 if (rhost == NULL) {
5777                         return WERR_NOMEM;
5778                 }
5779         }
5780
5781         werr = print_job_start(p->session_info,
5782                                p->msg_ctx,
5783                                rhost,
5784                                snum,
5785                                info_1->document_name,
5786                                info_1->output_file,
5787                                Printer->devmode,
5788                                &Printer->jobid);
5789
5790         /* An error occured in print_job_start() so return an appropriate
5791            NT error code. */
5792
5793         if (!W_ERROR_IS_OK(werr)) {
5794                 return werr;
5795         }
5796
5797         Printer->document_started = true;
5798         *r->out.job_id = Printer->jobid;
5799
5800         return WERR_OK;
5801 }
5802
5803 /****************************************************************
5804  _spoolss_EndDocPrinter
5805 ****************************************************************/
5806
5807 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5808                               struct spoolss_EndDocPrinter *r)
5809 {
5810         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5811         NTSTATUS status;
5812         int snum;
5813
5814         if (!Printer) {
5815                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5816                         OUR_HANDLE(r->in.handle)));
5817                 return WERR_BADFID;
5818         }
5819
5820         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5821                 return WERR_BADFID;
5822         }
5823
5824         Printer->document_started = false;
5825         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5826         if (!NT_STATUS_IS_OK(status)) {
5827                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5828                           "print_job_end failed [%s]\n",
5829                           nt_errstr(status)));
5830         }
5831
5832         Printer->jobid = 0;
5833         return ntstatus_to_werror(status);
5834 }
5835
5836 /****************************************************************
5837  _spoolss_WritePrinter
5838 ****************************************************************/
5839
5840 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5841                              struct spoolss_WritePrinter *r)
5842 {
5843         ssize_t buffer_written;
5844         int snum;
5845         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5846
5847         if (!Printer) {
5848                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5849                         OUR_HANDLE(r->in.handle)));
5850                 *r->out.num_written = r->in._data_size;
5851                 return WERR_BADFID;
5852         }
5853
5854         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5855                 return WERR_BADFID;
5856
5857         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5858         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5859                                                    snum, Printer->jobid,
5860                                                    (const char *)r->in.data.data,
5861                                                    (size_t)r->in._data_size);
5862         if (buffer_written == (ssize_t)-1) {
5863                 *r->out.num_written = 0;
5864                 if (errno == ENOSPC)
5865                         return WERR_NO_SPOOL_SPACE;
5866                 else
5867                         return WERR_ACCESS_DENIED;
5868         }
5869
5870         *r->out.num_written = r->in._data_size;
5871
5872         return WERR_OK;
5873 }
5874
5875 /********************************************************************
5876  * api_spoolss_getprinter
5877  * called from the spoolss dispatcher
5878  *
5879  ********************************************************************/
5880
5881 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5882                               struct pipes_struct *p)
5883 {
5884         const struct auth_session_info *session_info = p->session_info;
5885         int snum;
5886         WERROR errcode = WERR_BADFUNC;
5887         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5888
5889         if (!Printer) {
5890                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5891                         OUR_HANDLE(handle)));
5892                 return WERR_BADFID;
5893         }
5894
5895         if (!get_printer_snum(p, handle, &snum, NULL))
5896                 return WERR_BADFID;
5897
5898         switch (command) {
5899         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5900                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5901                 break;
5902         case SPOOLSS_PRINTER_CONTROL_RESUME:
5903         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5904                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5905                 break;
5906         case SPOOLSS_PRINTER_CONTROL_PURGE:
5907                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5908                 break;
5909         default:
5910                 return WERR_UNKNOWN_LEVEL;
5911         }
5912
5913         return errcode;
5914 }
5915
5916
5917 /****************************************************************
5918  _spoolss_AbortPrinter
5919  * From MSDN: "Deletes printer's spool file if printer is configured
5920  * for spooling"
5921 ****************************************************************/
5922
5923 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5924                              struct spoolss_AbortPrinter *r)
5925 {
5926         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5927         int             snum;
5928         WERROR          errcode = WERR_OK;
5929
5930         if (!Printer) {
5931                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5932                         OUR_HANDLE(r->in.handle)));
5933                 return WERR_BADFID;
5934         }
5935
5936         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5937                 return WERR_BADFID;
5938
5939         if (!Printer->document_started) {
5940                 return WERR_SPL_NO_STARTDOC;
5941         }
5942
5943         errcode = print_job_delete(p->session_info,
5944                                    p->msg_ctx,
5945                                    snum,
5946                                    Printer->jobid);
5947
5948         return errcode;
5949 }
5950
5951 /********************************************************************
5952  * called by spoolss_api_setprinter
5953  * when updating a printer description
5954  ********************************************************************/
5955
5956 static WERROR update_printer_sec(struct policy_handle *handle,
5957                                  struct pipes_struct *p,
5958                                  struct sec_desc_buf *secdesc_ctr)
5959 {
5960         struct spoolss_security_descriptor *new_secdesc = NULL;
5961         struct spoolss_security_descriptor *old_secdesc = NULL;
5962         const char *printer;
5963         WERROR result;
5964         int snum;
5965         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5966         struct dcerpc_binding_handle *b;
5967         TALLOC_CTX *tmp_ctx = NULL;
5968
5969         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5970                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5971                          OUR_HANDLE(handle)));
5972
5973                 result = WERR_BADFID;
5974                 goto done;
5975         }
5976
5977         if (secdesc_ctr == NULL) {
5978                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5979                 result = WERR_INVALID_PARAM;
5980                 goto done;
5981         }
5982         printer = lp_const_servicename(snum);
5983
5984         /* Check the user has permissions to change the security
5985            descriptor.  By experimentation with two NT machines, the user
5986            requires Full Access to the printer to change security
5987            information. */
5988
5989         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5990                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5991                 result = WERR_ACCESS_DENIED;
5992                 goto done;
5993         }
5994
5995         tmp_ctx = talloc_new(p->mem_ctx);
5996         if (!tmp_ctx) {
5997                 return WERR_NOMEM;
5998         }
5999
6000         result = winreg_printer_binding_handle(tmp_ctx,
6001                                                get_session_info_system(),
6002                                                p->msg_ctx,
6003                                                &b);
6004         if (!W_ERROR_IS_OK(result)) {
6005                 goto done;
6006         }
6007
6008         /* NT seems to like setting the security descriptor even though
6009            nothing may have actually changed. */
6010         result = winreg_get_printer_secdesc(tmp_ctx, b,
6011                                             printer,
6012                                             &old_secdesc);
6013         if (!W_ERROR_IS_OK(result)) {
6014                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6015                 result = WERR_BADFID;
6016                 goto done;
6017         }
6018
6019         if (DEBUGLEVEL >= 10) {
6020                 struct security_acl *the_acl;
6021                 int i;
6022
6023                 the_acl = old_secdesc->dacl;
6024                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6025                            printer, the_acl->num_aces));
6026
6027                 for (i = 0; i < the_acl->num_aces; i++) {
6028                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6029                                            &the_acl->aces[i].trustee),
6030                                   the_acl->aces[i].access_mask));
6031                 }
6032
6033                 the_acl = secdesc_ctr->sd->dacl;
6034
6035                 if (the_acl) {
6036                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6037                                    printer, the_acl->num_aces));
6038
6039                         for (i = 0; i < the_acl->num_aces; i++) {
6040                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6041                                                    &the_acl->aces[i].trustee),
6042                                            the_acl->aces[i].access_mask));
6043                         }
6044                 } else {
6045                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6046                 }
6047         }
6048
6049         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6050         if (new_secdesc == NULL) {
6051                 result = WERR_NOMEM;
6052                 goto done;
6053         }
6054
6055         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6056                 result = WERR_OK;
6057                 goto done;
6058         }
6059
6060         result = winreg_set_printer_secdesc(tmp_ctx, b,
6061                                             printer,
6062                                             new_secdesc);
6063
6064 done:
6065         talloc_free(tmp_ctx);
6066         return result;
6067 }
6068
6069 /********************************************************************
6070  Canonicalize printer info from a client
6071  ********************************************************************/
6072
6073 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6074                              struct spoolss_SetPrinterInfo2 *info2,
6075                              int snum)
6076 {
6077         fstring printername;
6078         const char *p;
6079
6080         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6081                 "portname=%s drivername=%s comment=%s location=%s\n",
6082                 info2->servername, info2->printername, info2->sharename,
6083                 info2->portname, info2->drivername, info2->comment,
6084                 info2->location));
6085
6086         /* we force some elements to "correct" values */
6087         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6088         if (info2->servername == NULL) {
6089                 return false;
6090         }
6091         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6092         if (info2->sharename == NULL) {
6093                 return false;
6094         }
6095
6096         /* check to see if we allow printername != sharename */
6097         if (lp_force_printername(snum)) {
6098                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6099                                         lp_netbios_name(), info2->sharename);
6100         } else {
6101                 /* make sure printername is in \\server\printername format */
6102                 fstrcpy(printername, info2->printername);
6103                 p = printername;
6104                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6105                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6106                                 p++;
6107                 }
6108
6109                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6110                                         lp_netbios_name(), p);
6111         }
6112         if (info2->printername == NULL) {
6113                 return false;
6114         }
6115
6116         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6117         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6118
6119         return true;
6120 }
6121
6122 /****************************************************************************
6123 ****************************************************************************/
6124
6125 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6126 {
6127         char *cmd = lp_addport_cmd(talloc_tos());
6128         char *command = NULL;
6129         int ret;
6130         bool is_print_op = false;
6131
6132         if ( !*cmd ) {
6133                 return WERR_ACCESS_DENIED;
6134         }
6135
6136         command = talloc_asprintf(ctx,
6137                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6138         if (!command) {
6139                 return WERR_NOMEM;
6140         }
6141
6142         if ( token )
6143                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6144
6145         DEBUG(10,("Running [%s]\n", command));
6146
6147         /********* BEGIN SePrintOperatorPrivilege **********/
6148
6149         if ( is_print_op )
6150                 become_root();
6151
6152         ret = smbrun(command, NULL);
6153
6154         if ( is_print_op )
6155                 unbecome_root();
6156
6157         /********* END SePrintOperatorPrivilege **********/
6158
6159         DEBUGADD(10,("returned [%d]\n", ret));
6160
6161         TALLOC_FREE(command);
6162
6163         if ( ret != 0 ) {
6164                 return WERR_ACCESS_DENIED;
6165         }
6166
6167         return WERR_OK;
6168 }
6169
6170 /****************************************************************************
6171 ****************************************************************************/
6172
6173 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6174                                    int snum)
6175 {
6176         /*
6177          * As we do not know if we are embedded in the file server process
6178          * or not, we have to pretend that all shares are in use.
6179          */
6180         return true;
6181 }
6182
6183 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6184                              struct spoolss_SetPrinterInfo2 *info2,
6185                              const char *remote_machine,
6186                              struct messaging_context *msg_ctx)
6187 {
6188         char *cmd = lp_addprinter_cmd(talloc_tos());
6189         char **qlines;
6190         char *command = NULL;
6191         int numlines;
6192         int ret;
6193         int fd;
6194         bool is_print_op = false;
6195
6196         if (!remote_machine) {
6197                 return false;
6198         }
6199
6200         command = talloc_asprintf(ctx,
6201                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6202                         cmd, info2->printername, info2->sharename,
6203                         info2->portname, info2->drivername,
6204                         info2->location, info2->comment, remote_machine);
6205         if (!command) {
6206                 return false;
6207         }
6208
6209         if ( token )
6210                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6211
6212         DEBUG(10,("Running [%s]\n", command));
6213
6214         /********* BEGIN SePrintOperatorPrivilege **********/
6215
6216         if ( is_print_op )
6217                 become_root();
6218
6219         if ( (ret = smbrun(command, &fd)) == 0 ) {
6220                 /* Tell everyone we updated smb.conf. */
6221                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6222         }
6223
6224         if ( is_print_op )
6225                 unbecome_root();
6226
6227         /********* END SePrintOperatorPrivilege **********/
6228
6229         DEBUGADD(10,("returned [%d]\n", ret));
6230
6231         TALLOC_FREE(command);
6232
6233         if ( ret != 0 ) {
6234                 if (fd != -1)
6235                         close(fd);
6236                 return false;
6237         }
6238
6239         /* reload our services immediately */
6240         become_root();
6241         reload_services(NULL, spoolss_conn_snum_used, false);
6242         unbecome_root();
6243
6244         numlines = 0;
6245         /* Get lines and convert them back to dos-codepage */
6246         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6247         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6248         close(fd);
6249
6250         /* Set the portname to what the script says the portname should be. */
6251         /* but don't require anything to be return from the script exit a good error code */
6252
6253         if (numlines) {
6254                 /* Set the portname to what the script says the portname should be. */
6255                 info2->portname = talloc_strdup(ctx, qlines[0]);
6256                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6257         }
6258
6259         TALLOC_FREE(qlines);
6260         return true;
6261 }
6262
6263 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6264                                const struct auth_session_info *session_info,
6265                                struct messaging_context *msg_ctx,
6266                                int snum,
6267                                struct spoolss_SetPrinterInfo2 *printer,
6268                                struct spoolss_PrinterInfo2 *old_printer)
6269 {
6270         bool force_update = (old_printer == NULL);
6271         const char *dnsdomname;
6272         const char *longname;
6273         const char *uncname;
6274         const char *spooling;
6275         DATA_BLOB buffer;
6276         WERROR result = WERR_OK;
6277         struct dcerpc_binding_handle *b;
6278         TALLOC_CTX *tmp_ctx;
6279         bool ok;
6280
6281         tmp_ctx = talloc_new(mem_ctx);
6282         if (!tmp_ctx) {
6283                 return WERR_NOMEM;
6284         }
6285
6286         result = winreg_printer_binding_handle(tmp_ctx,
6287                                                session_info,
6288                                                msg_ctx,
6289                                                &b);
6290         if (!W_ERROR_IS_OK(result)) {
6291                 goto done;
6292         }
6293
6294         if (printer->drivername != NULL &&
6295             (force_update ||
6296              !strequal(printer->drivername, old_printer->drivername))) {
6297                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6298                 if (!ok) {
6299                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6300                         result = WERR_INVALID_DATA;
6301                         goto done;
6302                 }
6303                 result = winreg_set_printer_dataex(tmp_ctx, b,
6304                                           printer->sharename,
6305                                           SPOOL_DSSPOOLER_KEY,
6306                                           SPOOL_REG_DRIVERNAME,
6307                                           REG_SZ,
6308                                           buffer.data,
6309                                           buffer.length);
6310                 if (!W_ERROR_IS_OK(result)) {
6311                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6312                         goto done;
6313                 }
6314
6315                 if (!force_update) {
6316                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6317                                 printer->drivername));
6318
6319                         notify_printer_driver(server_event_context(), msg_ctx,
6320                                               snum, printer->drivername ?
6321                                               printer->drivername : "");
6322                 }
6323         }
6324
6325         if (printer->comment != NULL &&
6326             (force_update ||
6327              !strequal(printer->comment, old_printer->comment))) {
6328                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6329                 if (!ok) {
6330                         DEBUG(0, ("comment data corrupted\n"));
6331                         result = WERR_INVALID_DATA;
6332                         goto done;
6333                 }
6334                 result = winreg_set_printer_dataex(tmp_ctx, b,
6335                                           printer->sharename,
6336                                           SPOOL_DSSPOOLER_KEY,
6337                                           SPOOL_REG_DESCRIPTION,
6338                                           REG_SZ,
6339                                           buffer.data,
6340                                           buffer.length);
6341                 if (!W_ERROR_IS_OK(result)) {
6342                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6343                         goto done;
6344                 }
6345
6346                 if (!force_update) {
6347                         notify_printer_comment(server_event_context(), msg_ctx,
6348                                                snum, printer->comment ?
6349                                                printer->comment : "");
6350                 }
6351         }
6352
6353         if (printer->sharename != NULL &&
6354             (force_update ||
6355              !strequal(printer->sharename, old_printer->sharename))) {
6356                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6357                 if (!ok) {
6358                         DEBUG(0, ("sharename data corrupted\n"));
6359                         result = WERR_INVALID_DATA;
6360                         goto done;
6361                 }
6362                 result = 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                 if (!W_ERROR_IS_OK(result)) {
6370                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6371                         goto done;
6372                 }
6373
6374                 if (!force_update) {
6375                         notify_printer_sharename(server_event_context(),
6376                                                  msg_ctx,
6377                                                  snum, printer->sharename ?
6378                                                  printer->sharename : "");
6379                 }
6380         }
6381
6382         if (printer->printername != NULL &&
6383             (force_update ||
6384              !strequal(printer->printername, old_printer->printername))) {
6385                 const char *p;
6386
6387                 p = strrchr(printer->printername, '\\' );
6388                 if (p != NULL) {
6389                         p++;
6390                 } else {
6391                         p = printer->printername;
6392                 }
6393
6394                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6395                 if (!ok) {
6396                         DEBUG(0, ("printername data corrupted\n"));
6397                         result = WERR_INVALID_DATA;
6398                         goto done;
6399                 }
6400                 result = winreg_set_printer_dataex(tmp_ctx, b,
6401                                           printer->sharename,
6402                                           SPOOL_DSSPOOLER_KEY,
6403                                           SPOOL_REG_PRINTERNAME,
6404                                           REG_SZ,
6405                                           buffer.data,
6406                                           buffer.length);
6407                 if (!W_ERROR_IS_OK(result)) {
6408                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6409                         goto done;
6410                 }
6411
6412                 if (!force_update) {
6413                         notify_printer_printername(server_event_context(),
6414                                                    msg_ctx, snum, p ? p : "");
6415                 }
6416         }
6417
6418         if (printer->portname != NULL &&
6419             (force_update ||
6420              !strequal(printer->portname, old_printer->portname))) {
6421                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6422                 if (!ok) {
6423                         DEBUG(0, ("portname data corrupted\n"));
6424                         result = WERR_INVALID_DATA;
6425                         goto done;
6426                 }
6427                 result = winreg_set_printer_dataex(tmp_ctx, b,
6428                                           printer->sharename,
6429                                           SPOOL_DSSPOOLER_KEY,
6430                                           SPOOL_REG_PORTNAME,
6431                                           REG_SZ,
6432                                           buffer.data,
6433                                           buffer.length);
6434                 if (!W_ERROR_IS_OK(result)) {
6435                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6436                         goto done;
6437                 }
6438
6439                 if (!force_update) {
6440                         notify_printer_port(server_event_context(),
6441                                             msg_ctx, snum, printer->portname ?
6442                                             printer->portname : "");
6443                 }
6444         }
6445
6446         if (printer->location != NULL &&
6447             (force_update ||
6448              !strequal(printer->location, old_printer->location))) {
6449                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6450                 if (!ok) {
6451                         DEBUG(0, ("location data corrupted\n"));
6452                         result = WERR_INVALID_DATA;
6453                         goto done;
6454                 }
6455                 result = winreg_set_printer_dataex(tmp_ctx, b,
6456                                           printer->sharename,
6457                                           SPOOL_DSSPOOLER_KEY,
6458                                           SPOOL_REG_LOCATION,
6459                                           REG_SZ,
6460                                           buffer.data,
6461                                           buffer.length);
6462                 if (!W_ERROR_IS_OK(result)) {
6463                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6464                         goto done;
6465                 }
6466
6467                 if (!force_update) {
6468                         notify_printer_location(server_event_context(),
6469                                                 msg_ctx, snum,
6470                                                 printer->location ?
6471                                                 printer->location : "");
6472                 }
6473         }
6474
6475         if (printer->sepfile != NULL &&
6476             (force_update ||
6477              !strequal(printer->sepfile, old_printer->sepfile))) {
6478                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6479                 if (!ok) {
6480                         DEBUG(0, ("sepfile data corrupted\n"));
6481                         result = WERR_INVALID_DATA;
6482                         goto done;
6483                 }
6484                 result = winreg_set_printer_dataex(tmp_ctx, b,
6485                                           printer->sharename,
6486                                           SPOOL_DSSPOOLER_KEY,
6487                                           SPOOL_REG_PRINTSEPARATORFILE,
6488                                           REG_SZ,
6489                                           buffer.data,
6490                                           buffer.length);
6491                 if (!W_ERROR_IS_OK(result)) {
6492                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6493                         goto done;
6494                 }
6495
6496                 if (!force_update) {
6497                         notify_printer_sepfile(server_event_context(),
6498                                                msg_ctx, snum,
6499                                                printer->sepfile ?
6500                                                printer->sepfile : "");
6501                 }
6502         }
6503
6504         if (printer->starttime != 0 &&
6505             (force_update ||
6506              printer->starttime != old_printer->starttime)) {
6507                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6508                 SIVAL(buffer.data, 0, printer->starttime);
6509                 result = winreg_set_printer_dataex(tmp_ctx, b,
6510                                           printer->sharename,
6511                                           SPOOL_DSSPOOLER_KEY,
6512                                           SPOOL_REG_PRINTSTARTTIME,
6513                                           REG_DWORD,
6514                                           buffer.data,
6515                                           buffer.length);
6516                 if (!W_ERROR_IS_OK(result)) {
6517                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6518                         goto done;
6519                 }
6520         }
6521
6522         if (printer->untiltime != 0 &&
6523             (force_update ||
6524              printer->untiltime != old_printer->untiltime)) {
6525                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6526                 SIVAL(buffer.data, 0, printer->untiltime);
6527                 result = winreg_set_printer_dataex(tmp_ctx, b,
6528                                           printer->sharename,
6529                                           SPOOL_DSSPOOLER_KEY,
6530                                           SPOOL_REG_PRINTENDTIME,
6531                                           REG_DWORD,
6532                                           buffer.data,
6533                                           buffer.length);
6534                 if (!W_ERROR_IS_OK(result)) {
6535                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6536                         goto done;
6537                 }
6538         }
6539
6540         if (force_update || printer->priority != old_printer->priority) {
6541                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6542                 SIVAL(buffer.data, 0, printer->priority);
6543                 result = winreg_set_printer_dataex(tmp_ctx, b,
6544                                           printer->sharename,
6545                                           SPOOL_DSSPOOLER_KEY,
6546                                           SPOOL_REG_PRIORITY,
6547                                           REG_DWORD,
6548                                           buffer.data,
6549                                           buffer.length);
6550                 if (!W_ERROR_IS_OK(result)) {
6551                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6552                         goto done;
6553                 }
6554         }
6555
6556         if (force_update || printer->attributes != old_printer->attributes) {
6557                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6558                 SIVAL(buffer.data, 0, (printer->attributes &
6559                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6560                 result = winreg_set_printer_dataex(tmp_ctx, b,
6561                                           printer->sharename,
6562                                           SPOOL_DSSPOOLER_KEY,
6563                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6564                                           REG_DWORD,
6565                                           buffer.data,
6566                                           buffer.length);
6567                 if (!W_ERROR_IS_OK(result)) {
6568                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6569                         goto done;
6570                 }
6571
6572                 switch (printer->attributes & 0x3) {
6573                         case 0:
6574                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6575                                 break;
6576                         case 1:
6577                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6578                                 break;
6579                         case 2:
6580                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6581                                 break;
6582                         default:
6583                                 spooling = "unknown";
6584                 }
6585                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6586                 if (!ok) {
6587                         DEBUG(0, ("printSpooling data corrupted\n"));
6588                         result = WERR_INVALID_DATA;
6589                         goto done;
6590                 }
6591                 winreg_set_printer_dataex(tmp_ctx, b,
6592                                           printer->sharename,
6593                                           SPOOL_DSSPOOLER_KEY,
6594                                           SPOOL_REG_PRINTSPOOLING,
6595                                           REG_SZ,
6596                                           buffer.data,
6597                                           buffer.length);
6598         }
6599
6600         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6601         if (!ok) {
6602                 DEBUG(0, ("shortServerName data corrupted\n"));
6603                 result = WERR_INVALID_DATA;
6604                 goto done;
6605         }
6606         result = winreg_set_printer_dataex(tmp_ctx, b,
6607                                   printer->sharename,
6608                                   SPOOL_DSSPOOLER_KEY,
6609                                   SPOOL_REG_SHORTSERVERNAME,
6610                                   REG_SZ,
6611                                   buffer.data,
6612                                   buffer.length);
6613         if (!W_ERROR_IS_OK(result)) {
6614                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6615                 goto done;
6616         }
6617
6618         dnsdomname = get_mydnsfullname();
6619         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6620                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6621         } else {
6622                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6623         }
6624         if (longname == NULL) {
6625                 result = WERR_NOMEM;
6626                 goto done;
6627         }
6628
6629         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6630         if (!ok) {
6631                 DEBUG(0, ("longname data corrupted\n"));
6632                 result = WERR_INVALID_DATA;
6633                 goto done;
6634         }
6635         result = winreg_set_printer_dataex(tmp_ctx, b,
6636                                            printer->sharename,
6637                                            SPOOL_DSSPOOLER_KEY,
6638                                            SPOOL_REG_SERVERNAME,
6639                                            REG_SZ,
6640                                            buffer.data,
6641                                            buffer.length);
6642         if (!W_ERROR_IS_OK(result)) {
6643                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6644                 goto done;
6645         }
6646
6647         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6648                                   lp_netbios_name(), printer->sharename);
6649         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6650         if (!ok) {
6651                 DEBUG(0, ("uncName data corrupted\n"));
6652                 result = WERR_INVALID_DATA;
6653                 goto done;
6654         }
6655         result = winreg_set_printer_dataex(tmp_ctx, b,
6656                                   printer->sharename,
6657                                   SPOOL_DSSPOOLER_KEY,
6658                                   SPOOL_REG_UNCNAME,
6659                                   REG_SZ,
6660                                   buffer.data,
6661                                   buffer.length);
6662         if (!W_ERROR_IS_OK(result)) {
6663                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6664                 goto done;
6665         }
6666
6667 done:
6668         talloc_free(tmp_ctx);
6669         return result;
6670 }
6671
6672 /********************************************************************
6673  * Called by spoolss_api_setprinter
6674  * when updating a printer description.
6675  ********************************************************************/
6676
6677 static WERROR update_printer(struct pipes_struct *p,
6678                              struct policy_handle *handle,
6679                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6680                              struct spoolss_DeviceMode *devmode)
6681 {
6682         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6683         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6684         struct spoolss_PrinterInfo2 *old_printer;
6685         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6686         int snum;
6687         WERROR result = WERR_OK;
6688         TALLOC_CTX *tmp_ctx;
6689         struct dcerpc_binding_handle *b;
6690
6691         DEBUG(8,("update_printer\n"));
6692
6693         tmp_ctx = talloc_new(p->mem_ctx);
6694         if (tmp_ctx == NULL) {
6695                 return WERR_NOMEM;
6696         }
6697
6698         if (!Printer) {
6699                 result = WERR_BADFID;
6700                 goto done;
6701         }
6702
6703         if (!get_printer_snum(p, handle, &snum, NULL)) {
6704                 result = WERR_BADFID;
6705                 goto done;
6706         }
6707
6708         result = winreg_printer_binding_handle(tmp_ctx,
6709                                                get_session_info_system(),
6710                                                p->msg_ctx,
6711                                                &b);
6712         if (!W_ERROR_IS_OK(result)) {
6713                 goto done;
6714         }
6715
6716         result = winreg_get_printer(tmp_ctx, b,
6717                                     lp_const_servicename(snum),
6718                                     &old_printer);
6719         if (!W_ERROR_IS_OK(result)) {
6720                 result = WERR_BADFID;
6721                 goto done;
6722         }
6723
6724         /* Do sanity check on the requested changes for Samba */
6725         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6726                 result = WERR_INVALID_PARAM;
6727                 goto done;
6728         }
6729
6730         /* FIXME!!! If the driver has changed we really should verify that
6731            it is installed before doing much else   --jerry */
6732
6733         /* Check calling user has permission to update printer description */
6734         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6735                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6736                 result = WERR_ACCESS_DENIED;
6737                 goto done;
6738         }
6739
6740         /* Call addprinter hook */
6741         /* Check changes to see if this is really needed */
6742
6743         if (*lp_addprinter_cmd(talloc_tos()) &&
6744                         (!strequal(printer->drivername, old_printer->drivername) ||
6745                          !strequal(printer->comment, old_printer->comment) ||
6746                          !strequal(printer->portname, old_printer->portname) ||
6747                          !strequal(printer->location, old_printer->location)) )
6748         {
6749                 char *raddr;
6750
6751                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6752                                                          p->mem_ctx);
6753                 if (raddr == NULL) {
6754                         return WERR_NOMEM;
6755                 }
6756
6757                 /* add_printer_hook() will call reload_services() */
6758                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6759                                       printer, raddr,
6760                                       p->msg_ctx)) {
6761                         result = WERR_ACCESS_DENIED;
6762                         goto done;
6763                 }
6764         }
6765
6766         result = update_dsspooler(tmp_ctx,
6767                                   get_session_info_system(),
6768                                   p->msg_ctx,
6769                                   snum,
6770                                   printer,
6771                                   old_printer);
6772         if (!W_ERROR_IS_OK(result)) {
6773                 goto done;
6774         }
6775
6776         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6777
6778         if (devmode == NULL) {
6779                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6780         }
6781         result = winreg_update_printer(tmp_ctx, b,
6782                                        printer->sharename,
6783                                        printer_mask,
6784                                        printer,
6785                                        devmode,
6786                                        NULL);
6787
6788 done:
6789         talloc_free(tmp_ctx);
6790
6791         return result;
6792 }
6793
6794 /****************************************************************************
6795 ****************************************************************************/
6796 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6797                                            struct policy_handle *handle,
6798                                            struct spoolss_SetPrinterInfo7 *info7)
6799 {
6800 #ifdef HAVE_ADS
6801         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6802         WERROR result;
6803         int snum;
6804         struct printer_handle *Printer;
6805
6806         if ( lp_security() != SEC_ADS ) {
6807                 return WERR_UNKNOWN_LEVEL;
6808         }
6809
6810         Printer = find_printer_index_by_hnd(p, handle);
6811
6812         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6813
6814         if (!Printer)
6815                 return WERR_BADFID;
6816
6817         if (!get_printer_snum(p, handle, &snum, NULL))
6818                 return WERR_BADFID;
6819
6820         result = winreg_get_printer_internal(p->mem_ctx,
6821                                     get_session_info_system(),
6822                                     p->msg_ctx,
6823                                     lp_servicename(talloc_tos(), snum),
6824                                     &pinfo2);
6825         if (!W_ERROR_IS_OK(result)) {
6826                 return WERR_BADFID;
6827         }
6828
6829         nt_printer_publish(pinfo2,
6830                            get_session_info_system(),
6831                            p->msg_ctx,
6832                            pinfo2,
6833                            info7->action);
6834
6835         TALLOC_FREE(pinfo2);
6836         return WERR_OK;
6837 #else
6838         return WERR_UNKNOWN_LEVEL;
6839 #endif
6840 }
6841
6842 /********************************************************************
6843  ********************************************************************/
6844
6845 static WERROR update_printer_devmode(struct pipes_struct *p,
6846                                      struct policy_handle *handle,
6847                                      struct spoolss_DeviceMode *devmode)
6848 {
6849         int snum;
6850         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6851         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6852
6853         DEBUG(8,("update_printer_devmode\n"));
6854
6855         if (!Printer) {
6856                 return WERR_BADFID;
6857         }
6858
6859         if (!get_printer_snum(p, handle, &snum, NULL)) {
6860                 return WERR_BADFID;
6861         }
6862
6863         /* Check calling user has permission to update printer description */
6864         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6865                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6866                 return WERR_ACCESS_DENIED;
6867         }
6868
6869         return winreg_update_printer_internal(p->mem_ctx,
6870                                      get_session_info_system(),
6871                                      p->msg_ctx,
6872                                      lp_const_servicename(snum),
6873                                      info2_mask,
6874                                      NULL,
6875                                      devmode,
6876                                      NULL);
6877 }
6878
6879
6880 /****************************************************************
6881  _spoolss_SetPrinter
6882 ****************************************************************/
6883
6884 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6885                            struct spoolss_SetPrinter *r)
6886 {
6887         WERROR result;
6888
6889         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6890
6891         if (!Printer) {
6892                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6893                         OUR_HANDLE(r->in.handle)));
6894                 return WERR_BADFID;
6895         }
6896
6897         /* check the level */
6898         switch (r->in.info_ctr->level) {
6899                 case 0:
6900                         return control_printer(r->in.handle, r->in.command, p);
6901                 case 2:
6902                         result = update_printer(p, r->in.handle,
6903                                                 r->in.info_ctr,
6904                                                 r->in.devmode_ctr->devmode);
6905                         if (!W_ERROR_IS_OK(result))
6906                                 return result;
6907                         if (r->in.secdesc_ctr->sd)
6908                                 result = update_printer_sec(r->in.handle, p,
6909                                                             r->in.secdesc_ctr);
6910                         return result;
6911                 case 3:
6912                         return update_printer_sec(r->in.handle, p,
6913                                                   r->in.secdesc_ctr);
6914                 case 7:
6915                         return publish_or_unpublish_printer(p, r->in.handle,
6916                                                             r->in.info_ctr->info.info7);
6917                 case 8:
6918                         return update_printer_devmode(p, r->in.handle,
6919                                                       r->in.devmode_ctr->devmode);
6920                 default:
6921                         return WERR_UNKNOWN_LEVEL;
6922         }
6923 }
6924
6925 /****************************************************************
6926  _spoolss_FindClosePrinterNotify
6927 ****************************************************************/
6928
6929 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6930                                        struct spoolss_FindClosePrinterNotify *r)
6931 {
6932         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6933
6934         if (!Printer) {
6935                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6936                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6937                 return WERR_BADFID;
6938         }
6939
6940         if (Printer->notify.cli_chan != NULL &&
6941             Printer->notify.cli_chan->active_connections > 0) {
6942                 int snum = -1;
6943
6944                 if (Printer->printer_type == SPLHND_PRINTER) {
6945                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6946                                 return WERR_BADFID;
6947                         }
6948                 }
6949
6950                 srv_spoolss_replycloseprinter(snum, Printer);
6951         }
6952
6953         Printer->notify.flags=0;
6954         Printer->notify.options=0;
6955         Printer->notify.localmachine[0]='\0';
6956         Printer->notify.printerlocal=0;
6957         TALLOC_FREE(Printer->notify.option);
6958
6959         return WERR_OK;
6960 }
6961
6962 /****************************************************************
6963  _spoolss_AddJob
6964 ****************************************************************/
6965
6966 WERROR _spoolss_AddJob(struct pipes_struct *p,
6967                        struct spoolss_AddJob *r)
6968 {
6969         if (!r->in.buffer && (r->in.offered != 0)) {
6970                 return WERR_INVALID_PARAM;
6971         }
6972
6973         /* this is what a NT server returns for AddJob. AddJob must fail on
6974          * non-local printers */
6975
6976         if (r->in.level != 1) {
6977                 return WERR_UNKNOWN_LEVEL;
6978         }
6979
6980         return WERR_INVALID_PARAM;
6981 }
6982
6983 /****************************************************************************
6984 fill_job_info1
6985 ****************************************************************************/
6986
6987 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6988                              struct spoolss_JobInfo1 *r,
6989                              const print_queue_struct *queue,
6990                              int position, int snum,
6991                              struct spoolss_PrinterInfo2 *pinfo2)
6992 {
6993         struct tm *t;
6994
6995         t = gmtime(&queue->time);
6996
6997         r->job_id               = queue->sysjob;
6998
6999         r->printer_name         = lp_servicename(mem_ctx, snum);
7000         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7001         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7002         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7003         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7004         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7005         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7006         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7007         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7008         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7009         r->text_status          = talloc_strdup(mem_ctx, "");
7010         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7011
7012         r->status               = nt_printj_status(queue->status);
7013         r->priority             = queue->priority;
7014         r->position             = position;
7015         r->total_pages          = queue->page_count;
7016         r->pages_printed        = 0; /* ??? */
7017
7018         init_systemtime(&r->submitted, t);
7019
7020         return WERR_OK;
7021 }
7022
7023 /****************************************************************************
7024 fill_job_info2
7025 ****************************************************************************/
7026
7027 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7028                              struct spoolss_JobInfo2 *r,
7029                              const print_queue_struct *queue,
7030                              int position, int snum,
7031                              struct spoolss_PrinterInfo2 *pinfo2,
7032                              struct spoolss_DeviceMode *devmode)
7033 {
7034         struct tm *t;
7035
7036         t = gmtime(&queue->time);
7037
7038         r->job_id               = queue->sysjob;
7039
7040         r->printer_name         = lp_servicename(mem_ctx, snum);
7041         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7042         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7043         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7044         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7045         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7046         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7047         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7048         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7049         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7050         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7051         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7052         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7053         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7054         r->parameters           = talloc_strdup(mem_ctx, "");
7055         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7056         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7057         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7058
7059         r->devmode              = devmode;
7060
7061         r->text_status          = talloc_strdup(mem_ctx, "");
7062         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7063
7064         r->secdesc              = NULL;
7065
7066         r->status               = nt_printj_status(queue->status);
7067         r->priority             = queue->priority;
7068         r->position             = position;
7069         r->start_time           = 0;
7070         r->until_time           = 0;
7071         r->total_pages          = queue->page_count;
7072         r->size                 = queue->size;
7073         init_systemtime(&r->submitted, t);
7074         r->time                 = 0;
7075         r->pages_printed        = 0; /* ??? */
7076
7077         return WERR_OK;
7078 }
7079
7080 /****************************************************************************
7081 fill_job_info3
7082 ****************************************************************************/
7083
7084 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7085                              struct spoolss_JobInfo3 *r,
7086                              const print_queue_struct *queue,
7087                              const print_queue_struct *next_queue,
7088                              int position, int snum,
7089                              struct spoolss_PrinterInfo2 *pinfo2)
7090 {
7091         r->job_id               = queue->sysjob;
7092         r->next_job_id          = 0;
7093         if (next_queue) {
7094                 r->next_job_id  = next_queue->sysjob;
7095         }
7096         r->reserved             = 0;
7097
7098         return WERR_OK;
7099 }
7100
7101 /****************************************************************************
7102  Enumjobs at level 1.
7103 ****************************************************************************/
7104
7105 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7106                               const print_queue_struct *queue,
7107                               uint32_t num_queues, int snum,
7108                               struct spoolss_PrinterInfo2 *pinfo2,
7109                               union spoolss_JobInfo **info_p,
7110                               uint32_t *count)
7111 {
7112         union spoolss_JobInfo *info;
7113         int i;
7114         WERROR result = WERR_OK;
7115
7116         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7117         W_ERROR_HAVE_NO_MEMORY(info);
7118
7119         *count = num_queues;
7120
7121         for (i=0; i<*count; i++) {
7122                 result = fill_job_info1(info,
7123                                         &info[i].info1,
7124                                         &queue[i],
7125                                         i,
7126                                         snum,
7127                                         pinfo2);
7128                 if (!W_ERROR_IS_OK(result)) {
7129                         goto out;
7130                 }
7131         }
7132
7133  out:
7134         if (!W_ERROR_IS_OK(result)) {
7135                 TALLOC_FREE(info);
7136                 *count = 0;
7137                 return result;
7138         }
7139
7140         *info_p = info;
7141
7142         return WERR_OK;
7143 }
7144
7145 /****************************************************************************
7146  Enumjobs at level 2.
7147 ****************************************************************************/
7148
7149 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7150                               const print_queue_struct *queue,
7151                               uint32_t num_queues, int snum,
7152                               struct spoolss_PrinterInfo2 *pinfo2,
7153                               union spoolss_JobInfo **info_p,
7154                               uint32_t *count)
7155 {
7156         union spoolss_JobInfo *info;
7157         int i;
7158         WERROR result = WERR_OK;
7159
7160         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7161         W_ERROR_HAVE_NO_MEMORY(info);
7162
7163         *count = num_queues;
7164
7165         for (i=0; i<*count; i++) {
7166                 struct spoolss_DeviceMode *devmode;
7167
7168                 result = spoolss_create_default_devmode(info,
7169                                                         pinfo2->printername,
7170                                                         &devmode);
7171                 if (!W_ERROR_IS_OK(result)) {
7172                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7173                         goto out;
7174                 }
7175
7176                 result = fill_job_info2(info,
7177                                         &info[i].info2,
7178                                         &queue[i],
7179                                         i,
7180                                         snum,
7181                                         pinfo2,
7182                                         devmode);
7183                 if (!W_ERROR_IS_OK(result)) {
7184                         goto out;
7185                 }
7186         }
7187
7188  out:
7189         if (!W_ERROR_IS_OK(result)) {
7190                 TALLOC_FREE(info);
7191                 *count = 0;
7192                 return result;
7193         }
7194
7195         *info_p = info;
7196
7197         return WERR_OK;
7198 }
7199
7200 /****************************************************************************
7201  Enumjobs at level 3.
7202 ****************************************************************************/
7203
7204 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7205                               const print_queue_struct *queue,
7206                               uint32_t num_queues, int snum,
7207                               struct spoolss_PrinterInfo2 *pinfo2,
7208                               union spoolss_JobInfo **info_p,
7209                               uint32_t *count)
7210 {
7211         union spoolss_JobInfo *info;
7212         int i;
7213         WERROR result = WERR_OK;
7214
7215         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7216         W_ERROR_HAVE_NO_MEMORY(info);
7217
7218         *count = num_queues;
7219
7220         for (i=0; i<*count; i++) {
7221                 const print_queue_struct *next_queue = NULL;
7222
7223                 if (i+1 < *count) {
7224                         next_queue = &queue[i+1];
7225                 }
7226
7227                 result = fill_job_info3(info,
7228                                         &info[i].info3,
7229                                         &queue[i],
7230                                         next_queue,
7231                                         i,
7232                                         snum,
7233                                         pinfo2);
7234                 if (!W_ERROR_IS_OK(result)) {
7235                         goto out;
7236                 }
7237         }
7238
7239  out:
7240         if (!W_ERROR_IS_OK(result)) {
7241                 TALLOC_FREE(info);
7242                 *count = 0;
7243                 return result;
7244         }
7245
7246         *info_p = info;
7247
7248         return WERR_OK;
7249 }
7250
7251 /****************************************************************
7252  _spoolss_EnumJobs
7253 ****************************************************************/
7254
7255 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7256                          struct spoolss_EnumJobs *r)
7257 {
7258         WERROR result;
7259         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7260         int snum;
7261         print_status_struct prt_status;
7262         print_queue_struct *queue = NULL;
7263         uint32_t count;
7264
7265         /* that's an [in out] buffer */
7266
7267         if (!r->in.buffer && (r->in.offered != 0)) {
7268                 return WERR_INVALID_PARAM;
7269         }
7270
7271         DEBUG(4,("_spoolss_EnumJobs\n"));
7272
7273         *r->out.needed = 0;
7274         *r->out.count = 0;
7275         *r->out.info = NULL;
7276
7277         /* lookup the printer snum and tdb entry */
7278
7279         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7280                 return WERR_BADFID;
7281         }
7282
7283         result = winreg_get_printer_internal(p->mem_ctx,
7284                                     get_session_info_system(),
7285                                     p->msg_ctx,
7286                                     lp_const_servicename(snum),
7287                                     &pinfo2);
7288         if (!W_ERROR_IS_OK(result)) {
7289                 return result;
7290         }
7291
7292         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7293         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7294                 count, prt_status.status, prt_status.message));
7295
7296         if (count == 0) {
7297                 SAFE_FREE(queue);
7298                 TALLOC_FREE(pinfo2);
7299                 return WERR_OK;
7300         }
7301
7302         switch (r->in.level) {
7303         case 1:
7304                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7305                                          pinfo2, r->out.info, r->out.count);
7306                 break;
7307         case 2:
7308                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7309                                          pinfo2, r->out.info, r->out.count);
7310                 break;
7311         case 3:
7312                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7313                                          pinfo2, r->out.info, r->out.count);
7314                 break;
7315         default:
7316                 result = WERR_UNKNOWN_LEVEL;
7317                 break;
7318         }
7319
7320         SAFE_FREE(queue);
7321         TALLOC_FREE(pinfo2);
7322
7323         if (!W_ERROR_IS_OK(result)) {
7324                 return result;
7325         }
7326
7327         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7328                                                      spoolss_EnumJobs,
7329                                                      *r->out.info, r->in.level,
7330                                                      *r->out.count);
7331         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7332         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7333
7334         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7335 }
7336
7337 /****************************************************************
7338  _spoolss_ScheduleJob
7339 ****************************************************************/
7340
7341 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7342                             struct spoolss_ScheduleJob *r)
7343 {
7344         return WERR_OK;
7345 }
7346
7347 /****************************************************************
7348 ****************************************************************/
7349
7350 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7351                                struct messaging_context *msg_ctx,
7352                                const char *printer_name,
7353                                uint32_t job_id,
7354                                struct spoolss_SetJobInfo1 *r)
7355 {
7356         char *old_doc_name;
7357
7358         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7359                 return WERR_BADFID;
7360         }
7361
7362         if (strequal(old_doc_name, r->document_name)) {
7363                 return WERR_OK;
7364         }
7365
7366         if (!print_job_set_name(server_event_context(), msg_ctx,
7367                                 printer_name, job_id, r->document_name)) {
7368                 return WERR_BADFID;
7369         }
7370
7371         return WERR_OK;
7372 }
7373
7374 /****************************************************************
7375  _spoolss_SetJob
7376 ****************************************************************/
7377
7378 WERROR _spoolss_SetJob(struct pipes_struct *p,
7379                        struct spoolss_SetJob *r)
7380 {
7381         const struct auth_session_info *session_info = p->session_info;
7382         int snum;
7383         WERROR errcode = WERR_BADFUNC;
7384
7385         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7386                 return WERR_BADFID;
7387         }
7388
7389         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7390                 return WERR_INVALID_PRINTER_NAME;
7391         }
7392
7393         switch (r->in.command) {
7394         case SPOOLSS_JOB_CONTROL_CANCEL:
7395         case SPOOLSS_JOB_CONTROL_DELETE:
7396                 errcode = print_job_delete(session_info, p->msg_ctx,
7397                                            snum, r->in.job_id);
7398                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7399                         errcode = WERR_OK;
7400                 }
7401                 break;
7402         case SPOOLSS_JOB_CONTROL_PAUSE:
7403                 errcode = print_job_pause(session_info, p->msg_ctx,
7404                                           snum, r->in.job_id);
7405                 break;
7406         case SPOOLSS_JOB_CONTROL_RESTART:
7407         case SPOOLSS_JOB_CONTROL_RESUME:
7408                 errcode = print_job_resume(session_info, p->msg_ctx,
7409                                            snum, r->in.job_id);
7410                 break;
7411         case 0:
7412                 errcode = WERR_OK;
7413                 break;
7414         default:
7415                 return WERR_UNKNOWN_LEVEL;
7416         }
7417
7418         if (!W_ERROR_IS_OK(errcode)) {
7419                 return errcode;
7420         }
7421
7422         if (r->in.ctr == NULL) {
7423                 return errcode;
7424         }
7425
7426         switch (r->in.ctr->level) {
7427         case 1:
7428                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7429                                            lp_const_servicename(snum),
7430                                            r->in.job_id,
7431                                            r->in.ctr->info.info1);
7432                 break;
7433         case 2:
7434         case 3:
7435         case 4:
7436         default:
7437                 return WERR_UNKNOWN_LEVEL;
7438         }
7439
7440         return errcode;
7441 }
7442
7443 /****************************************************************************
7444  Enumerates all printer drivers by level and architecture.
7445 ****************************************************************************/
7446
7447 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7448                                                        const struct auth_session_info *session_info,
7449                                                        struct messaging_context *msg_ctx,
7450                                                        const char *servername,
7451                                                        const char *architecture,
7452                                                        uint32_t level,
7453                                                        union spoolss_DriverInfo **info_p,
7454                                                        uint32_t *count_p)
7455 {
7456         int i;
7457         uint32_t version;
7458         struct spoolss_DriverInfo8 *driver;
7459         union spoolss_DriverInfo *info = NULL;
7460         uint32_t count = 0;
7461         WERROR result = WERR_OK;
7462         uint32_t num_drivers;
7463         const char **drivers;
7464         struct dcerpc_binding_handle *b;
7465         TALLOC_CTX *tmp_ctx = NULL;
7466
7467         *count_p = 0;
7468         *info_p = NULL;
7469
7470         tmp_ctx = talloc_new(mem_ctx);
7471         if (!tmp_ctx) {
7472                 return WERR_NOMEM;
7473         }
7474
7475         result = winreg_printer_binding_handle(tmp_ctx,
7476                                                session_info,
7477                                                msg_ctx,
7478                                                &b);
7479         if (!W_ERROR_IS_OK(result)) {
7480                 goto out;
7481         }
7482
7483         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7484                 result = winreg_get_driver_list(tmp_ctx, b,
7485                                                 architecture, version,
7486                                                 &num_drivers, &drivers);
7487                 if (!W_ERROR_IS_OK(result)) {
7488                         goto out;
7489                 }
7490                 DEBUG(4, ("we have:[%d] drivers in environment"
7491                           " [%s] and version [%d]\n",
7492                           num_drivers, architecture, version));
7493
7494                 if (num_drivers != 0) {
7495                         info = talloc_realloc(tmp_ctx, info,
7496                                                     union spoolss_DriverInfo,
7497                                                     count + num_drivers);
7498                         if (!info) {
7499                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7500                                         "failed to enlarge driver info buffer!\n"));
7501                                 result = WERR_NOMEM;
7502                                 goto out;
7503                         }
7504                 }
7505
7506                 for (i = 0; i < num_drivers; i++) {
7507                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7508
7509                         result = winreg_get_driver(tmp_ctx, b,
7510                                                    architecture, drivers[i],
7511                                                    version, &driver);
7512                         if (!W_ERROR_IS_OK(result)) {
7513                                 goto out;
7514                         }
7515
7516                         switch (level) {
7517                         case 1:
7518                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7519                                                                    driver, servername);
7520                                 break;
7521                         case 2:
7522                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7523                                                                    driver, servername);
7524                                 break;
7525                         case 3:
7526                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7527                                                                    driver, servername);
7528                                 break;
7529                         case 4:
7530                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7531                                                                    driver, servername);
7532                                 break;
7533                         case 5:
7534                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7535                                                                    driver, servername);
7536                                 break;
7537                         case 6:
7538                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7539                                                                    driver, servername);
7540                                 break;
7541                         case 8:
7542                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7543                                                                    driver, servername);
7544                                 break;
7545                         default:
7546                                 result = WERR_UNKNOWN_LEVEL;
7547                                 break;
7548                         }
7549
7550                         TALLOC_FREE(driver);
7551
7552                         if (!W_ERROR_IS_OK(result)) {
7553                                 goto out;
7554                         }
7555                 }
7556
7557                 count += num_drivers;
7558                 TALLOC_FREE(drivers);
7559         }
7560
7561 out:
7562         if (W_ERROR_IS_OK(result)) {
7563                 *info_p = talloc_move(mem_ctx, &info);
7564                 *count_p = count;
7565         }
7566
7567         talloc_free(tmp_ctx);
7568         return result;
7569 }
7570
7571 /****************************************************************************
7572  Enumerates all printer drivers by level.
7573 ****************************************************************************/
7574
7575 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7576                                        const struct auth_session_info *session_info,
7577                                        struct messaging_context *msg_ctx,
7578                                        const char *servername,
7579                                        const char *architecture,
7580                                        uint32_t level,
7581                                        union spoolss_DriverInfo **info_p,
7582                                        uint32_t *count_p)
7583 {
7584         uint32_t a,i;
7585         WERROR result = WERR_OK;
7586
7587         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7588
7589                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7590
7591                         union spoolss_DriverInfo *info = NULL;
7592                         uint32_t count = 0;
7593
7594                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7595                                                                           session_info,
7596                                                                           msg_ctx,
7597                                                                           servername,
7598                                                                           archi_table[a].long_archi,
7599                                                                           level,
7600                                                                           &info,
7601                                                                           &count);
7602                         if (!W_ERROR_IS_OK(result)) {
7603                                 continue;
7604                         }
7605
7606                         for (i=0; i < count; i++) {
7607                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7608                                              info[i], info_p, count_p);
7609                         }
7610                 }
7611
7612                 return result;
7613         }
7614
7615         return enumprinterdrivers_level_by_architecture(mem_ctx,
7616                                                         session_info,
7617                                                         msg_ctx,
7618                                                         servername,
7619                                                         architecture,
7620                                                         level,
7621                                                         info_p,
7622                                                         count_p);
7623 }
7624
7625 /****************************************************************
7626  _spoolss_EnumPrinterDrivers
7627 ****************************************************************/
7628
7629 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7630                                    struct spoolss_EnumPrinterDrivers *r)
7631 {
7632         const char *cservername;
7633         WERROR result;
7634
7635         /* that's an [in out] buffer */
7636
7637         if (!r->in.buffer && (r->in.offered != 0)) {
7638                 return WERR_INVALID_PARAM;
7639         }
7640
7641         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7642
7643         *r->out.needed = 0;
7644         *r->out.count = 0;
7645         *r->out.info = NULL;
7646
7647         cservername = canon_servername(r->in.server);
7648
7649         if (!is_myname_or_ipaddr(cservername)) {
7650                 return WERR_UNKNOWN_PRINTER_DRIVER;
7651         }
7652
7653         result = enumprinterdrivers_level(p->mem_ctx,
7654                                           get_session_info_system(),
7655                                           p->msg_ctx,
7656                                           cservername,
7657                                           r->in.environment,
7658                                           r->in.level,
7659                                           r->out.info,
7660                                           r->out.count);
7661         if (!W_ERROR_IS_OK(result)) {
7662                 return result;
7663         }
7664
7665         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7666                                                      spoolss_EnumPrinterDrivers,
7667                                                      *r->out.info, r->in.level,
7668                                                      *r->out.count);
7669         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7670         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7671
7672         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7673 }
7674
7675 /****************************************************************
7676  _spoolss_EnumForms
7677 ****************************************************************/
7678
7679 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7680                           struct spoolss_EnumForms *r)
7681 {
7682         WERROR result;
7683
7684         *r->out.count = 0;
7685         *r->out.needed = 0;
7686         *r->out.info = NULL;
7687
7688         /* that's an [in out] buffer */
7689
7690         if (!r->in.buffer && (r->in.offered != 0) ) {
7691                 return WERR_INVALID_PARAM;
7692         }
7693
7694         DEBUG(4,("_spoolss_EnumForms\n"));
7695         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7696         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7697
7698         switch (r->in.level) {
7699         case 1:
7700                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7701                                                    get_session_info_system(),
7702                                                    p->msg_ctx,
7703                                                    r->out.count,
7704                                                    r->out.info);
7705                 break;
7706         default:
7707                 result = WERR_UNKNOWN_LEVEL;
7708                 break;
7709         }
7710
7711         if (!W_ERROR_IS_OK(result)) {
7712                 return result;
7713         }
7714
7715         if (*r->out.count == 0) {
7716                 return WERR_NO_MORE_ITEMS;
7717         }
7718
7719         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7720                                                      spoolss_EnumForms,
7721                                                      *r->out.info, r->in.level,
7722                                                      *r->out.count);
7723         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7724         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7725
7726         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7727 }
7728
7729 /****************************************************************
7730  _spoolss_GetForm
7731 ****************************************************************/
7732
7733 WERROR _spoolss_GetForm(struct pipes_struct *p,
7734                         struct spoolss_GetForm *r)
7735 {
7736         WERROR result;
7737
7738         /* that's an [in out] buffer */
7739
7740         if (!r->in.buffer && (r->in.offered != 0)) {
7741                 return WERR_INVALID_PARAM;
7742         }
7743
7744         DEBUG(4,("_spoolss_GetForm\n"));
7745         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7746         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7747
7748         switch (r->in.level) {
7749         case 1:
7750                 result = winreg_printer_getform1_internal(p->mem_ctx,
7751                                                  get_session_info_system(),
7752                                                  p->msg_ctx,
7753                                                  r->in.form_name,
7754                                                  &r->out.info->info1);
7755                 break;
7756         default:
7757                 result = WERR_UNKNOWN_LEVEL;
7758                 break;
7759         }
7760
7761         if (!W_ERROR_IS_OK(result)) {
7762                 TALLOC_FREE(r->out.info);
7763                 return result;
7764         }
7765
7766         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7767                                                r->out.info, r->in.level);
7768         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7769
7770         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7771 }
7772
7773 /****************************************************************************
7774 ****************************************************************************/
7775
7776 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7777                           struct spoolss_PortInfo1 *r,
7778                           const char *name)
7779 {
7780         r->port_name = talloc_strdup(mem_ctx, name);
7781         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7782
7783         return WERR_OK;
7784 }
7785
7786 /****************************************************************************
7787  TODO: This probably needs distinguish between TCP/IP and Local ports
7788  somehow.
7789 ****************************************************************************/
7790
7791 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7792                           struct spoolss_PortInfo2 *r,
7793                           const char *name)
7794 {
7795         r->port_name = talloc_strdup(mem_ctx, name);
7796         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7797
7798         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7799         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7800
7801         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7802         W_ERROR_HAVE_NO_MEMORY(r->description);
7803
7804         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7805         r->reserved = 0;
7806
7807         return WERR_OK;
7808 }
7809
7810
7811 /****************************************************************************
7812  wrapper around the enumer ports command
7813 ****************************************************************************/
7814
7815 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7816 {
7817         char *cmd = lp_enumports_cmd(talloc_tos());
7818         char **qlines = NULL;
7819         char *command = NULL;
7820         int numlines;
7821         int ret;
7822         int fd;
7823
7824         *count = 0;
7825         *lines = NULL;
7826
7827         /* if no hook then just fill in the default port */
7828
7829         if ( !*cmd ) {
7830                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7831                         return WERR_NOMEM;
7832                 }
7833                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7834                         TALLOC_FREE(qlines);
7835                         return WERR_NOMEM;
7836                 }
7837                 qlines[1] = NULL;
7838                 numlines = 1;
7839         }
7840         else {
7841                 /* we have a valid enumport command */
7842
7843                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7844                 if (!command) {
7845                         return WERR_NOMEM;
7846                 }
7847
7848                 DEBUG(10,("Running [%s]\n", command));
7849                 ret = smbrun(command, &fd);
7850                 DEBUG(10,("Returned [%d]\n", ret));
7851                 TALLOC_FREE(command);
7852                 if (ret != 0) {
7853                         if (fd != -1) {
7854                                 close(fd);
7855                         }
7856                         return WERR_ACCESS_DENIED;
7857                 }
7858
7859                 numlines = 0;
7860                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7861                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7862                 close(fd);
7863         }
7864
7865         *count = numlines;
7866         *lines = qlines;
7867
7868         return WERR_OK;
7869 }
7870
7871 /****************************************************************************
7872  enumports level 1.
7873 ****************************************************************************/
7874
7875 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7876                                 union spoolss_PortInfo **info_p,
7877                                 uint32_t *count)
7878 {
7879         union spoolss_PortInfo *info = NULL;
7880         int i=0;
7881         WERROR result = WERR_OK;
7882         char **qlines = NULL;
7883         int numlines = 0;
7884
7885         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7886         if (!W_ERROR_IS_OK(result)) {
7887                 goto out;
7888         }
7889
7890         if (numlines) {
7891                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7892                 if (!info) {
7893                         DEBUG(10,("Returning WERR_NOMEM\n"));
7894                         result = WERR_NOMEM;
7895                         goto out;
7896                 }
7897
7898                 for (i=0; i<numlines; i++) {
7899                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7900                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7901                         if (!W_ERROR_IS_OK(result)) {
7902                                 goto out;
7903                         }
7904                 }
7905         }
7906         TALLOC_FREE(qlines);
7907
7908 out:
7909         if (!W_ERROR_IS_OK(result)) {
7910                 TALLOC_FREE(info);
7911                 TALLOC_FREE(qlines);
7912                 *count = 0;
7913                 *info_p = NULL;
7914                 return result;
7915         }
7916
7917         *info_p = info;
7918         *count = numlines;
7919
7920         return WERR_OK;
7921 }
7922
7923 /****************************************************************************
7924  enumports level 2.
7925 ****************************************************************************/
7926
7927 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7928                                 union spoolss_PortInfo **info_p,
7929                                 uint32_t *count)
7930 {
7931         union spoolss_PortInfo *info = NULL;
7932         int i=0;
7933         WERROR result = WERR_OK;
7934         char **qlines = NULL;
7935         int numlines = 0;
7936
7937         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7938         if (!W_ERROR_IS_OK(result)) {
7939                 goto out;
7940         }
7941
7942         if (numlines) {
7943                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7944                 if (!info) {
7945                         DEBUG(10,("Returning WERR_NOMEM\n"));
7946                         result = WERR_NOMEM;
7947                         goto out;
7948                 }
7949
7950                 for (i=0; i<numlines; i++) {
7951                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7952                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7953                         if (!W_ERROR_IS_OK(result)) {
7954                                 goto out;
7955                         }
7956                 }
7957         }
7958         TALLOC_FREE(qlines);
7959
7960 out:
7961         if (!W_ERROR_IS_OK(result)) {
7962                 TALLOC_FREE(info);
7963                 TALLOC_FREE(qlines);
7964                 *count = 0;
7965                 *info_p = NULL;
7966                 return result;
7967         }
7968
7969         *info_p = info;
7970         *count = numlines;
7971
7972         return WERR_OK;
7973 }
7974
7975 /****************************************************************
7976  _spoolss_EnumPorts
7977 ****************************************************************/
7978
7979 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7980                           struct spoolss_EnumPorts *r)
7981 {
7982         WERROR result;
7983
7984         /* that's an [in out] buffer */
7985
7986         if (!r->in.buffer && (r->in.offered != 0)) {
7987                 return WERR_INVALID_PARAM;
7988         }
7989
7990         DEBUG(4,("_spoolss_EnumPorts\n"));
7991
7992         *r->out.count = 0;
7993         *r->out.needed = 0;
7994         *r->out.info = NULL;
7995
7996         switch (r->in.level) {
7997         case 1:
7998                 result = enumports_level_1(p->mem_ctx, r->out.info,
7999                                            r->out.count);
8000                 break;
8001         case 2:
8002                 result = enumports_level_2(p->mem_ctx, r->out.info,
8003                                            r->out.count);
8004                 break;
8005         default:
8006                 return WERR_UNKNOWN_LEVEL;
8007         }
8008
8009         if (!W_ERROR_IS_OK(result)) {
8010                 return result;
8011         }
8012
8013         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8014                                                      spoolss_EnumPorts,
8015                                                      *r->out.info, r->in.level,
8016                                                      *r->out.count);
8017         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8018         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8019
8020         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8021 }
8022
8023 /****************************************************************************
8024 ****************************************************************************/
8025
8026 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8027                                            const char *server,
8028                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8029                                            struct spoolss_DeviceMode *devmode,
8030                                            struct security_descriptor *secdesc,
8031                                            struct spoolss_UserLevelCtr *user_ctr,
8032                                            struct policy_handle *handle)
8033 {
8034         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8035         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8036         int     snum;
8037         WERROR err = WERR_OK;
8038
8039         /* samba does not have a concept of local, non-shared printers yet, so
8040          * make sure we always setup sharename - gd */
8041         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8042             (info2->printername != NULL && info2->printername[0] != '\0')) {
8043                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8044                         "no sharename has been set, setting printername %s as sharename\n",
8045                         info2->printername));
8046                 info2->sharename = info2->printername;
8047         }
8048
8049         /* check to see if the printer already exists */
8050         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8051                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8052                         info2->sharename));
8053                 return WERR_PRINTER_ALREADY_EXISTS;
8054         }
8055
8056         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8057                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8058                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8059                                 info2->printername));
8060                         return WERR_PRINTER_ALREADY_EXISTS;
8061                 }
8062         }
8063
8064         /* validate printer info struct */
8065         if (!info2->printername || strlen(info2->printername) == 0) {
8066                 return WERR_INVALID_PRINTER_NAME;
8067         }
8068         if (!info2->portname || strlen(info2->portname) == 0) {
8069                 return WERR_UNKNOWN_PORT;
8070         }
8071         if (!info2->drivername || strlen(info2->drivername) == 0) {
8072                 return WERR_UNKNOWN_PRINTER_DRIVER;
8073         }
8074         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8075                 return WERR_UNKNOWN_PRINTPROCESSOR;
8076         }
8077
8078         /* FIXME!!!  smbd should check to see if the driver is installed before
8079            trying to add a printer like this  --jerry */
8080
8081         if (*lp_addprinter_cmd(talloc_tos()) ) {
8082                 char *raddr;
8083
8084                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8085                                                          p->mem_ctx);
8086                 if (raddr == NULL) {
8087                         return WERR_NOMEM;
8088                 }
8089
8090                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8091                                        info2, raddr,
8092                                        p->msg_ctx) ) {
8093                         return WERR_ACCESS_DENIED;
8094                 }
8095         } else {
8096                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8097                         "smb.conf parameter \"addprinter command\" is defined. This "
8098                         "parameter must exist for this call to succeed\n",
8099                         info2->sharename ));
8100         }
8101
8102         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8103                 return WERR_ACCESS_DENIED;
8104         }
8105
8106         /* you must be a printer admin to add a new printer */
8107         if (!print_access_check(p->session_info,
8108                                 p->msg_ctx,
8109                                 snum,
8110                                 PRINTER_ACCESS_ADMINISTER)) {
8111                 return WERR_ACCESS_DENIED;
8112         }
8113
8114         /*
8115          * Do sanity check on the requested changes for Samba.
8116          */
8117
8118         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8119                 return WERR_INVALID_PARAM;
8120         }
8121
8122         if (devmode == NULL) {
8123                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8124         }
8125
8126         err = update_dsspooler(p->mem_ctx,
8127                                get_session_info_system(),
8128                                p->msg_ctx,
8129                                0,
8130                                info2,
8131                                NULL);
8132         if (!W_ERROR_IS_OK(err)) {
8133                 return err;
8134         }
8135
8136         err = winreg_update_printer_internal(p->mem_ctx,
8137                                     get_session_info_system(),
8138                                     p->msg_ctx,
8139                                     info2->sharename,
8140                                     info2_mask,
8141                                     info2,
8142                                     devmode,
8143                                     secdesc);
8144         if (!W_ERROR_IS_OK(err)) {
8145                 return err;
8146         }
8147
8148         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8149         if (!W_ERROR_IS_OK(err)) {
8150                 /* Handle open failed - remove addition. */
8151                 ZERO_STRUCTP(handle);
8152                 return err;
8153         }
8154
8155         return WERR_OK;
8156 }
8157
8158 /****************************************************************
8159  _spoolss_AddPrinterEx
8160 ****************************************************************/
8161
8162 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8163                              struct spoolss_AddPrinterEx *r)
8164 {
8165         switch (r->in.info_ctr->level) {
8166         case 1:
8167                 /* we don't handle yet */
8168                 /* but I know what to do ... */
8169                 return WERR_UNKNOWN_LEVEL;
8170         case 2:
8171                 return spoolss_addprinterex_level_2(p, r->in.server,
8172                                                     r->in.info_ctr,
8173                                                     r->in.devmode_ctr->devmode,
8174                                                     r->in.secdesc_ctr->sd,
8175                                                     r->in.userlevel_ctr,
8176                                                     r->out.handle);
8177         default:
8178                 return WERR_UNKNOWN_LEVEL;
8179         }
8180 }
8181
8182 /****************************************************************
8183  _spoolss_AddPrinter
8184 ****************************************************************/
8185
8186 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8187                            struct spoolss_AddPrinter *r)
8188 {
8189         struct spoolss_AddPrinterEx a;
8190         struct spoolss_UserLevelCtr userlevel_ctr;
8191
8192         ZERO_STRUCT(userlevel_ctr);
8193
8194         userlevel_ctr.level = 1;
8195
8196         a.in.server             = r->in.server;
8197         a.in.info_ctr           = r->in.info_ctr;
8198         a.in.devmode_ctr        = r->in.devmode_ctr;
8199         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8200         a.in.userlevel_ctr      = &userlevel_ctr;
8201         a.out.handle            = r->out.handle;
8202
8203         return _spoolss_AddPrinterEx(p, &a);
8204 }
8205
8206 /****************************************************************
8207  _spoolss_AddPrinterDriverEx
8208 ****************************************************************/
8209
8210 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8211                                    struct spoolss_AddPrinterDriverEx *r)
8212 {
8213         WERROR err = WERR_OK;
8214         const char *driver_name = NULL;
8215         uint32_t version;
8216         const char *fn;
8217
8218         switch (p->opnum) {
8219                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8220                         fn = "_spoolss_AddPrinterDriver";
8221                         break;
8222                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8223                         fn = "_spoolss_AddPrinterDriverEx";
8224                         break;
8225                 default:
8226                         return WERR_INVALID_PARAM;
8227         }
8228
8229         /*
8230          * we only support the semantics of AddPrinterDriver()
8231          * i.e. only copy files that are newer than existing ones
8232          */
8233
8234         if (r->in.flags == 0) {
8235                 return WERR_INVALID_PARAM;
8236         }
8237
8238         if (r->in.flags != APD_COPY_NEW_FILES) {
8239                 return WERR_ACCESS_DENIED;
8240         }
8241
8242         /* FIXME */
8243         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8244                 /* Clever hack from Martin Zielinski <mz@seh.de>
8245                  * to allow downgrade from level 8 (Vista).
8246                  */
8247                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8248                         r->in.info_ctr->level));
8249                 return WERR_UNKNOWN_LEVEL;
8250         }
8251
8252         DEBUG(5,("Cleaning driver's information\n"));
8253         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8254         if (!W_ERROR_IS_OK(err))
8255                 goto done;
8256
8257         DEBUG(5,("Moving driver to final destination\n"));
8258         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8259         if (!W_ERROR_IS_OK(err)) {
8260                 goto done;
8261         }
8262
8263         err = winreg_add_driver_internal(p->mem_ctx,
8264                                 get_session_info_system(),
8265                                 p->msg_ctx,
8266                                 r->in.info_ctr,
8267                                 &driver_name,
8268                                 &version);
8269         if (!W_ERROR_IS_OK(err)) {
8270                 goto done;
8271         }
8272
8273         /*
8274          * I think this is where he DrvUpgradePrinter() hook would be
8275          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8276          * server.  Right now, we just need to send ourselves a message
8277          * to update each printer bound to this driver.   --jerry
8278          */
8279
8280         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8281                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8282                         fn, driver_name));
8283         }
8284
8285 done:
8286         return err;
8287 }
8288
8289 /****************************************************************
8290  _spoolss_AddPrinterDriver
8291 ****************************************************************/
8292
8293 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8294                                  struct spoolss_AddPrinterDriver *r)
8295 {
8296         struct spoolss_AddPrinterDriverEx a;
8297
8298         switch (r->in.info_ctr->level) {
8299         case 2:
8300         case 3:
8301         case 4:
8302         case 5:
8303                 break;
8304         default:
8305                 return WERR_UNKNOWN_LEVEL;
8306         }
8307
8308         a.in.servername         = r->in.servername;
8309         a.in.info_ctr           = r->in.info_ctr;
8310         a.in.flags              = APD_COPY_NEW_FILES;
8311
8312         return _spoolss_AddPrinterDriverEx(p, &a);
8313 }
8314
8315 /****************************************************************************
8316 ****************************************************************************/
8317
8318 struct _spoolss_paths {
8319         int type;
8320         const char *share;
8321         const char *dir;
8322 };
8323
8324 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8325
8326 static const struct _spoolss_paths spoolss_paths[]= {
8327         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8328         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8329 };
8330
8331 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8332                                           const char *servername,
8333                                           const char *environment,
8334                                           int component,
8335                                           char **path)
8336 {
8337         const char *pservername = NULL;
8338         const char *long_archi;
8339         const char *short_archi;
8340
8341         *path = NULL;
8342
8343         /* environment may be empty */
8344         if (environment && strlen(environment)) {
8345                 long_archi = environment;
8346         } else {
8347                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8348                                                   "spoolss", "architecture",
8349                                                   SPOOLSS_ARCHITECTURE_NT_X86);
8350         }
8351
8352         /* servername may be empty */
8353         if (servername && strlen(servername)) {
8354                 pservername = canon_servername(servername);
8355
8356                 if (!is_myname_or_ipaddr(pservername)) {
8357                         return WERR_INVALID_PARAM;
8358                 }
8359         }
8360
8361         if (!(short_archi = get_short_archi(long_archi))) {
8362                 return WERR_INVALID_ENVIRONMENT;
8363         }
8364
8365         switch (component) {
8366         case SPOOLSS_PRTPROCS_PATH:
8367         case SPOOLSS_DRIVER_PATH:
8368                 if (pservername) {
8369                         *path = talloc_asprintf(mem_ctx,
8370                                         "\\\\%s\\%s\\%s",
8371                                         pservername,
8372                                         spoolss_paths[component].share,
8373                                         short_archi);
8374                 } else {
8375                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8376                                         SPOOLSS_DEFAULT_SERVER_PATH,
8377                                         spoolss_paths[component].dir,
8378                                         short_archi);
8379                 }
8380                 break;
8381         default:
8382                 return WERR_INVALID_PARAM;
8383         }
8384
8385         if (!*path) {
8386                 return WERR_NOMEM;
8387         }
8388
8389         return WERR_OK;
8390 }
8391
8392 /****************************************************************************
8393 ****************************************************************************/
8394
8395 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8396                                           const char *servername,
8397                                           const char *environment,
8398                                           struct spoolss_DriverDirectoryInfo1 *r)
8399 {
8400         WERROR werr;
8401         char *path = NULL;
8402
8403         werr = compose_spoolss_server_path(mem_ctx,
8404                                            servername,
8405                                            environment,
8406                                            SPOOLSS_DRIVER_PATH,
8407                                            &path);
8408         if (!W_ERROR_IS_OK(werr)) {
8409                 return werr;
8410         }
8411
8412         DEBUG(4,("printer driver directory: [%s]\n", path));
8413
8414         r->directory_name = path;
8415
8416         return WERR_OK;
8417 }
8418
8419 /****************************************************************
8420  _spoolss_GetPrinterDriverDirectory
8421 ****************************************************************/
8422
8423 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8424                                           struct spoolss_GetPrinterDriverDirectory *r)
8425 {
8426         WERROR werror;
8427
8428         /* that's an [in out] buffer */
8429
8430         if (!r->in.buffer && (r->in.offered != 0)) {
8431                 return WERR_INVALID_PARAM;
8432         }
8433
8434         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8435                 r->in.level));
8436
8437         *r->out.needed = 0;
8438
8439         /* r->in.level is ignored */
8440
8441         werror = getprinterdriverdir_level_1(p->mem_ctx,
8442                                              r->in.server,
8443                                              r->in.environment,
8444                                              &r->out.info->info1);
8445         if (!W_ERROR_IS_OK(werror)) {
8446                 TALLOC_FREE(r->out.info);
8447                 return werror;
8448         }
8449
8450         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8451                                                r->out.info, r->in.level);
8452         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8453
8454         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8455 }
8456
8457 /****************************************************************
8458  _spoolss_EnumPrinterData
8459 ****************************************************************/
8460
8461 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8462                                 struct spoolss_EnumPrinterData *r)
8463 {
8464         WERROR result;
8465         struct spoolss_EnumPrinterDataEx r2;
8466         uint32_t count;
8467         struct spoolss_PrinterEnumValues *info, *val = NULL;
8468         uint32_t needed;
8469
8470         r2.in.handle    = r->in.handle;
8471         r2.in.key_name  = "PrinterDriverData";
8472         r2.in.offered   = 0;
8473         r2.out.count    = &count;
8474         r2.out.info     = &info;
8475         r2.out.needed   = &needed;
8476
8477         result = _spoolss_EnumPrinterDataEx(p, &r2);
8478         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8479                 r2.in.offered = needed;
8480                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8481         }
8482         if (!W_ERROR_IS_OK(result)) {
8483                 return result;
8484         }
8485
8486         /*
8487          * The NT machine wants to know the biggest size of value and data
8488          *
8489          * cf: MSDN EnumPrinterData remark section
8490          */
8491
8492         if (!r->in.value_offered && !r->in.data_offered) {
8493                 uint32_t biggest_valuesize = 0;
8494                 uint32_t biggest_datasize = 0;
8495                 int i, name_length;
8496
8497                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8498
8499                 for (i=0; i<count; i++) {
8500
8501                         name_length = strlen(info[i].value_name);
8502                         if (strlen(info[i].value_name) > biggest_valuesize) {
8503                                 biggest_valuesize = name_length;
8504                         }
8505
8506                         if (info[i].data_length > biggest_datasize) {
8507                                 biggest_datasize = info[i].data_length;
8508                         }
8509
8510                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8511                                 biggest_datasize));
8512                 }
8513
8514                 /* the value is an UNICODE string but real_value_size is the length
8515                    in bytes including the trailing 0 */
8516
8517                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8518                 *r->out.data_needed  = biggest_datasize;
8519
8520                 DEBUG(6,("final values: [%d], [%d]\n",
8521                         *r->out.value_needed, *r->out.data_needed));
8522
8523                 return WERR_OK;
8524         }
8525
8526         if (r->in.enum_index < count) {
8527                 val = &info[r->in.enum_index];
8528         }
8529
8530         if (val == NULL) {
8531                 /* out_value should default to "" or else NT4 has
8532                    problems unmarshalling the response */
8533
8534                 if (r->in.value_offered) {
8535                         *r->out.value_needed = 1;
8536                         r->out.value_name = talloc_strdup(r, "");
8537                         if (!r->out.value_name) {
8538                                 return WERR_NOMEM;
8539                         }
8540                 } else {
8541                         r->out.value_name = NULL;
8542                         *r->out.value_needed = 0;
8543                 }
8544
8545                 /* the data is counted in bytes */
8546
8547                 *r->out.data_needed = r->in.data_offered;
8548
8549                 result = WERR_NO_MORE_ITEMS;
8550         } else {
8551                 /*
8552                  * the value is:
8553                  * - counted in bytes in the request
8554                  * - counted in UNICODE chars in the max reply
8555                  * - counted in bytes in the real size
8556                  *
8557                  * take a pause *before* coding not *during* coding
8558                  */
8559
8560                 /* name */
8561                 if (r->in.value_offered) {
8562                         r->out.value_name = talloc_strdup(r, val->value_name);
8563                         if (!r->out.value_name) {
8564                                 return WERR_NOMEM;
8565                         }
8566                         *r->out.value_needed = val->value_name_len;
8567                 } else {
8568                         r->out.value_name = NULL;
8569                         *r->out.value_needed = 0;
8570                 }
8571
8572                 /* type */
8573
8574                 *r->out.type = val->type;
8575
8576                 /* data - counted in bytes */
8577
8578                 /*
8579                  * See the section "Dynamically Typed Query Parameters"
8580                  * in MS-RPRN.
8581                  */
8582
8583                 if (r->out.data && val->data && val->data->data &&
8584                                 val->data_length && r->in.data_offered) {
8585                         memcpy(r->out.data, val->data->data,
8586                                 MIN(val->data_length,r->in.data_offered));
8587                 }
8588
8589                 *r->out.data_needed = val->data_length;
8590
8591                 result = WERR_OK;
8592         }
8593
8594         return result;
8595 }
8596
8597 /****************************************************************
8598  _spoolss_SetPrinterData
8599 ****************************************************************/
8600
8601 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8602                                struct spoolss_SetPrinterData *r)
8603 {
8604         struct spoolss_SetPrinterDataEx r2;
8605
8606         r2.in.handle            = r->in.handle;
8607         r2.in.key_name          = "PrinterDriverData";
8608         r2.in.value_name        = r->in.value_name;
8609         r2.in.type              = r->in.type;
8610         r2.in.data              = r->in.data;
8611         r2.in.offered           = r->in.offered;
8612
8613         return _spoolss_SetPrinterDataEx(p, &r2);
8614 }
8615
8616 /****************************************************************
8617  _spoolss_ResetPrinter
8618 ****************************************************************/
8619
8620 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8621                              struct spoolss_ResetPrinter *r)
8622 {
8623         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8624         int             snum;
8625
8626         DEBUG(5,("_spoolss_ResetPrinter\n"));
8627
8628         /*
8629          * All we do is to check to see if the handle and queue is valid.
8630          * This call really doesn't mean anything to us because we only
8631          * support RAW printing.   --jerry
8632          */
8633
8634         if (!Printer) {
8635                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8636                         OUR_HANDLE(r->in.handle)));
8637                 return WERR_BADFID;
8638         }
8639
8640         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8641                 return WERR_BADFID;
8642
8643
8644         /* blindly return success */
8645         return WERR_OK;
8646 }
8647
8648 /****************************************************************
8649  _spoolss_DeletePrinterData
8650 ****************************************************************/
8651
8652 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8653                                   struct spoolss_DeletePrinterData *r)
8654 {
8655         struct spoolss_DeletePrinterDataEx r2;
8656
8657         r2.in.handle            = r->in.handle;
8658         r2.in.key_name          = "PrinterDriverData";
8659         r2.in.value_name        = r->in.value_name;
8660
8661         return _spoolss_DeletePrinterDataEx(p, &r2);
8662 }
8663
8664 /****************************************************************
8665  _spoolss_AddForm
8666 ****************************************************************/
8667
8668 WERROR _spoolss_AddForm(struct pipes_struct *p,
8669                         struct spoolss_AddForm *r)
8670 {
8671         struct spoolss_AddFormInfo1 *form;
8672         int snum = -1;
8673         WERROR status = WERR_OK;
8674         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8675         struct dcerpc_binding_handle *b;
8676         TALLOC_CTX *tmp_ctx = NULL;
8677
8678         DEBUG(5,("_spoolss_AddForm\n"));
8679
8680         if (!Printer) {
8681                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8682                         OUR_HANDLE(r->in.handle)));
8683                 return WERR_BADFID;
8684         }
8685
8686         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8687            and not a printer admin, then fail */
8688
8689         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8690             !security_token_has_privilege(p->session_info->security_token,
8691                                           SEC_PRIV_PRINT_OPERATOR)) {
8692                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8693                 return WERR_ACCESS_DENIED;
8694         }
8695
8696         if (r->in.info_ctr->level != 1) {
8697                 return WERR_INVALID_LEVEL;
8698         }
8699
8700         form = r->in.info_ctr->info.info1;
8701         if (!form) {
8702                 return WERR_INVALID_PARAM;
8703         }
8704
8705         switch (form->flags) {
8706         case SPOOLSS_FORM_USER:
8707         case SPOOLSS_FORM_BUILTIN:
8708         case SPOOLSS_FORM_PRINTER:
8709                 break;
8710         default:
8711                 return WERR_INVALID_PARAM;
8712         }
8713
8714         tmp_ctx = talloc_new(p->mem_ctx);
8715         if (!tmp_ctx) {
8716                 return WERR_NOMEM;
8717         }
8718
8719         status = winreg_printer_binding_handle(tmp_ctx,
8720                                                get_session_info_system(),
8721                                                p->msg_ctx,
8722                                                &b);
8723         if (!W_ERROR_IS_OK(status)) {
8724                 goto done;
8725         }
8726
8727         status = winreg_printer_addform1(tmp_ctx, b, form);
8728         if (!W_ERROR_IS_OK(status)) {
8729                 goto done;
8730         }
8731
8732         /*
8733          * ChangeID must always be set if this is a printer
8734          */
8735         if (Printer->printer_type == SPLHND_PRINTER) {
8736                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8737                         status = WERR_BADFID;
8738                         goto done;
8739                 }
8740
8741                 status = winreg_printer_update_changeid(tmp_ctx, b,
8742                                                         lp_const_servicename(snum));
8743         }
8744
8745 done:
8746         talloc_free(tmp_ctx);
8747         return status;
8748 }
8749
8750 /****************************************************************
8751  _spoolss_DeleteForm
8752 ****************************************************************/
8753
8754 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8755                            struct spoolss_DeleteForm *r)
8756 {
8757         const char *form_name = r->in.form_name;
8758         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8759         int snum = -1;
8760         WERROR status = WERR_OK;
8761         struct dcerpc_binding_handle *b;
8762         TALLOC_CTX *tmp_ctx = NULL;
8763
8764         DEBUG(5,("_spoolss_DeleteForm\n"));
8765
8766         if (!Printer) {
8767                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8768                         OUR_HANDLE(r->in.handle)));
8769                 return WERR_BADFID;
8770         }
8771
8772         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8773             !security_token_has_privilege(p->session_info->security_token,
8774                                           SEC_PRIV_PRINT_OPERATOR)) {
8775                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8776                 return WERR_ACCESS_DENIED;
8777         }
8778
8779         tmp_ctx = talloc_new(p->mem_ctx);
8780         if (!tmp_ctx) {
8781                 return WERR_NOMEM;
8782         }
8783
8784         status = winreg_printer_binding_handle(tmp_ctx,
8785                                                get_session_info_system(),
8786                                                p->msg_ctx,
8787                                                &b);
8788         if (!W_ERROR_IS_OK(status)) {
8789                 goto done;
8790         }
8791
8792         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8793         if (!W_ERROR_IS_OK(status)) {
8794                 goto done;
8795         }
8796
8797         /*
8798          * ChangeID must always be set if this is a printer
8799          */
8800         if (Printer->printer_type == SPLHND_PRINTER) {
8801                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8802                         status = WERR_BADFID;
8803                         goto done;
8804                 }
8805
8806                 status = winreg_printer_update_changeid(tmp_ctx, b,
8807                                                         lp_const_servicename(snum));
8808         }
8809
8810 done:
8811         talloc_free(tmp_ctx);
8812         return status;
8813 }
8814
8815 /****************************************************************
8816  _spoolss_SetForm
8817 ****************************************************************/
8818
8819 WERROR _spoolss_SetForm(struct pipes_struct *p,
8820                         struct spoolss_SetForm *r)
8821 {
8822         struct spoolss_AddFormInfo1 *form;
8823         const char *form_name = r->in.form_name;
8824         int snum = -1;
8825         WERROR status = WERR_OK;
8826         struct dcerpc_binding_handle *b;
8827         TALLOC_CTX *tmp_ctx = NULL;
8828
8829         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8830
8831         DEBUG(5,("_spoolss_SetForm\n"));
8832
8833         if (!Printer) {
8834                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8835                         OUR_HANDLE(r->in.handle)));
8836                 return WERR_BADFID;
8837         }
8838
8839         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8840            and not a printer admin, then fail */
8841
8842         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8843              !security_token_has_privilege(p->session_info->security_token,
8844                                            SEC_PRIV_PRINT_OPERATOR)) {
8845                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8846                 return WERR_ACCESS_DENIED;
8847         }
8848
8849         if (r->in.info_ctr->level != 1) {
8850                 return WERR_INVALID_LEVEL;
8851         }
8852
8853         form = r->in.info_ctr->info.info1;
8854         if (!form) {
8855                 return WERR_INVALID_PARAM;
8856         }
8857
8858         tmp_ctx = talloc_new(p->mem_ctx);
8859         if (!tmp_ctx) {
8860                 return WERR_NOMEM;
8861         }
8862
8863         status = winreg_printer_binding_handle(tmp_ctx,
8864                                                get_session_info_system(),
8865                                                p->msg_ctx,
8866                                                &b);
8867         if (!W_ERROR_IS_OK(status)) {
8868                 goto done;
8869         }
8870
8871         status = winreg_printer_setform1(tmp_ctx, b,
8872                                          form_name,
8873                                          form);
8874         if (!W_ERROR_IS_OK(status)) {
8875                 goto done;
8876         }
8877
8878         /*
8879          * ChangeID must always be set if this is a printer
8880          */
8881         if (Printer->printer_type == SPLHND_PRINTER) {
8882                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8883                         status = WERR_BADFID;
8884                         goto done;
8885                 }
8886
8887                 status = winreg_printer_update_changeid(tmp_ctx, b,
8888                                                         lp_const_servicename(snum));
8889         }
8890
8891 done:
8892         talloc_free(tmp_ctx);
8893         return status;
8894 }
8895
8896 /****************************************************************************
8897  fill_print_processor1
8898 ****************************************************************************/
8899
8900 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8901                                     struct spoolss_PrintProcessorInfo1 *r,
8902                                     const char *print_processor_name)
8903 {
8904         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8905         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8906
8907         return WERR_OK;
8908 }
8909
8910 /****************************************************************************
8911  enumprintprocessors level 1.
8912 ****************************************************************************/
8913
8914 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8915                                           union spoolss_PrintProcessorInfo **info_p,
8916                                           uint32_t *count)
8917 {
8918         union spoolss_PrintProcessorInfo *info;
8919         WERROR result;
8920
8921         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8922         W_ERROR_HAVE_NO_MEMORY(info);
8923
8924         *count = 1;
8925
8926         result = fill_print_processor1(info, &info[0].info1, "winprint");
8927         if (!W_ERROR_IS_OK(result)) {
8928                 goto out;
8929         }
8930
8931  out:
8932         if (!W_ERROR_IS_OK(result)) {
8933                 TALLOC_FREE(info);
8934                 *count = 0;
8935                 return result;
8936         }
8937
8938         *info_p = info;
8939
8940         return WERR_OK;
8941 }
8942
8943 /****************************************************************
8944  _spoolss_EnumPrintProcessors
8945 ****************************************************************/
8946
8947 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8948                                     struct spoolss_EnumPrintProcessors *r)
8949 {
8950         WERROR result;
8951
8952         /* that's an [in out] buffer */
8953
8954         if (!r->in.buffer && (r->in.offered != 0)) {
8955                 return WERR_INVALID_PARAM;
8956         }
8957
8958         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8959
8960         /*
8961          * Enumerate the print processors ...
8962          *
8963          * Just reply with "winprint", to keep NT happy
8964          * and I can use my nice printer checker.
8965          */
8966
8967         *r->out.count = 0;
8968         *r->out.needed = 0;
8969         *r->out.info = NULL;
8970
8971         if (!get_short_archi(r->in.environment)) {
8972                 return WERR_INVALID_ENVIRONMENT;
8973         }
8974
8975         switch (r->in.level) {
8976         case 1:
8977                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8978                                                      r->out.count);
8979                 break;
8980         default:
8981                 return WERR_UNKNOWN_LEVEL;
8982         }
8983
8984         if (!W_ERROR_IS_OK(result)) {
8985                 return result;
8986         }
8987
8988         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8989                                                      spoolss_EnumPrintProcessors,
8990                                                      *r->out.info, r->in.level,
8991                                                      *r->out.count);
8992         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8993         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8994
8995         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8996 }
8997
8998 /****************************************************************************
8999  fill_printprocdatatype1
9000 ****************************************************************************/
9001
9002 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9003                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9004                                       const char *name_array)
9005 {
9006         r->name_array = talloc_strdup(mem_ctx, name_array);
9007         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9008
9009         return WERR_OK;
9010 }
9011
9012 /****************************************************************************
9013  enumprintprocdatatypes level 1.
9014 ****************************************************************************/
9015
9016 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9017                                              union spoolss_PrintProcDataTypesInfo **info_p,
9018                                              uint32_t *count)
9019 {
9020         WERROR result;
9021         union spoolss_PrintProcDataTypesInfo *info;
9022
9023         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9024         W_ERROR_HAVE_NO_MEMORY(info);
9025
9026         *count = 1;
9027
9028         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9029         if (!W_ERROR_IS_OK(result)) {
9030                 goto out;
9031         }
9032
9033  out:
9034         if (!W_ERROR_IS_OK(result)) {
9035                 TALLOC_FREE(info);
9036                 *count = 0;
9037                 return result;
9038         }
9039
9040         *info_p = info;
9041
9042         return WERR_OK;
9043 }
9044
9045 /****************************************************************
9046  _spoolss_EnumPrintProcDataTypes
9047 ****************************************************************/
9048
9049 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9050                                        struct spoolss_EnumPrintProcDataTypes *r)
9051 {
9052         WERROR result;
9053
9054         /* that's an [in out] buffer */
9055
9056         if (!r->in.buffer && (r->in.offered != 0)) {
9057                 return WERR_INVALID_PARAM;
9058         }
9059
9060         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9061
9062         *r->out.count = 0;
9063         *r->out.needed = 0;
9064         *r->out.info = NULL;
9065
9066         if (r->in.print_processor_name == NULL ||
9067             !strequal(r->in.print_processor_name, "winprint")) {
9068                 return WERR_UNKNOWN_PRINTPROCESSOR;
9069         }
9070
9071         switch (r->in.level) {
9072         case 1:
9073                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9074                                                         r->out.count);
9075                 break;
9076         default:
9077                 return WERR_UNKNOWN_LEVEL;
9078         }
9079
9080         if (!W_ERROR_IS_OK(result)) {
9081                 return result;
9082         }
9083
9084         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9085                                                      spoolss_EnumPrintProcDataTypes,
9086                                                      *r->out.info, r->in.level,
9087                                                      *r->out.count);
9088         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9089         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9090
9091         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9092 }
9093
9094 /****************************************************************************
9095  fill_monitor_1
9096 ****************************************************************************/
9097
9098 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9099                              struct spoolss_MonitorInfo1 *r,
9100                              const char *monitor_name)
9101 {
9102         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9103         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9104
9105         return WERR_OK;
9106 }
9107
9108 /****************************************************************************
9109  fill_monitor_2
9110 ****************************************************************************/
9111
9112 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9113                              struct spoolss_MonitorInfo2 *r,
9114                              const char *monitor_name,
9115                              const char *environment,
9116                              const char *dll_name)
9117 {
9118         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9119         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9120         r->environment                  = talloc_strdup(mem_ctx, environment);
9121         W_ERROR_HAVE_NO_MEMORY(r->environment);
9122         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9123         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9124
9125         return WERR_OK;
9126 }
9127
9128 /****************************************************************************
9129  enumprintmonitors level 1.
9130 ****************************************************************************/
9131
9132 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9133                                         union spoolss_MonitorInfo **info_p,
9134                                         uint32_t *count)
9135 {
9136         union spoolss_MonitorInfo *info;
9137         WERROR result = WERR_OK;
9138
9139         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9140         W_ERROR_HAVE_NO_MEMORY(info);
9141
9142         *count = 2;
9143
9144         result = fill_monitor_1(info, &info[0].info1,
9145                                 SPL_LOCAL_PORT);
9146         if (!W_ERROR_IS_OK(result)) {
9147                 goto out;
9148         }
9149
9150         result = fill_monitor_1(info, &info[1].info1,
9151                                 SPL_TCPIP_PORT);
9152         if (!W_ERROR_IS_OK(result)) {
9153                 goto out;
9154         }
9155
9156 out:
9157         if (!W_ERROR_IS_OK(result)) {
9158                 TALLOC_FREE(info);
9159                 *count = 0;
9160                 return result;
9161         }
9162
9163         *info_p = info;
9164
9165         return WERR_OK;
9166 }
9167
9168 /****************************************************************************
9169  enumprintmonitors level 2.
9170 ****************************************************************************/
9171
9172 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9173                                         union spoolss_MonitorInfo **info_p,
9174                                         uint32_t *count)
9175 {
9176         union spoolss_MonitorInfo *info;
9177         WERROR result = WERR_OK;
9178
9179         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9180         W_ERROR_HAVE_NO_MEMORY(info);
9181
9182         *count = 2;
9183
9184         result = fill_monitor_2(info, &info[0].info2,
9185                                 SPL_LOCAL_PORT,
9186                                 "Windows NT X86", /* FIXME */
9187                                 "localmon.dll");
9188         if (!W_ERROR_IS_OK(result)) {
9189                 goto out;
9190         }
9191
9192         result = fill_monitor_2(info, &info[1].info2,
9193                                 SPL_TCPIP_PORT,
9194                                 "Windows NT X86", /* FIXME */
9195                                 "tcpmon.dll");
9196         if (!W_ERROR_IS_OK(result)) {
9197                 goto out;
9198         }
9199
9200 out:
9201         if (!W_ERROR_IS_OK(result)) {
9202                 TALLOC_FREE(info);
9203                 *count = 0;
9204                 return result;
9205         }
9206
9207         *info_p = info;
9208
9209         return WERR_OK;
9210 }
9211
9212 /****************************************************************
9213  _spoolss_EnumMonitors
9214 ****************************************************************/
9215
9216 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9217                              struct spoolss_EnumMonitors *r)
9218 {
9219         WERROR result;
9220
9221         /* that's an [in out] buffer */
9222
9223         if (!r->in.buffer && (r->in.offered != 0)) {
9224                 return WERR_INVALID_PARAM;
9225         }
9226
9227         DEBUG(5,("_spoolss_EnumMonitors\n"));
9228
9229         /*
9230          * Enumerate the print monitors ...
9231          *
9232          * Just reply with "Local Port", to keep NT happy
9233          * and I can use my nice printer checker.
9234          */
9235
9236         *r->out.count = 0;
9237         *r->out.needed = 0;
9238         *r->out.info = NULL;
9239
9240         switch (r->in.level) {
9241         case 1:
9242                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9243                                                    r->out.count);
9244                 break;
9245         case 2:
9246                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9247                                                    r->out.count);
9248                 break;
9249         default:
9250                 return WERR_UNKNOWN_LEVEL;
9251         }
9252
9253         if (!W_ERROR_IS_OK(result)) {
9254                 return result;
9255         }
9256
9257         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9258                                                      spoolss_EnumMonitors,
9259                                                      *r->out.info, r->in.level,
9260                                                      *r->out.count);
9261         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9262         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9263
9264         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9265 }
9266
9267 /****************************************************************************
9268 ****************************************************************************/
9269
9270 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9271                              const print_queue_struct *queue,
9272                              int count, int snum,
9273                              struct spoolss_PrinterInfo2 *pinfo2,
9274                              uint32_t jobid,
9275                              struct spoolss_JobInfo1 *r)
9276 {
9277         int i = 0;
9278         bool found = false;
9279
9280         for (i=0; i<count; i++) {
9281                 if (queue[i].sysjob == (int)jobid) {
9282                         found = true;
9283                         break;
9284                 }
9285         }
9286
9287         if (found == false) {
9288                 /* NT treats not found as bad param... yet another bad choice */
9289                 return WERR_INVALID_PARAM;
9290         }
9291
9292         return fill_job_info1(mem_ctx,
9293                               r,
9294                               &queue[i],
9295                               i,
9296                               snum,
9297                               pinfo2);
9298 }
9299
9300 /****************************************************************************
9301 ****************************************************************************/
9302
9303 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9304                              const print_queue_struct *queue,
9305                              int count, int snum,
9306                              struct spoolss_PrinterInfo2 *pinfo2,
9307                              uint32_t jobid,
9308                              struct spoolss_JobInfo2 *r)
9309 {
9310         int i = 0;
9311         bool found = false;
9312         struct spoolss_DeviceMode *devmode;
9313         WERROR result;
9314
9315         for (i=0; i<count; i++) {
9316                 if (queue[i].sysjob == (int)jobid) {
9317                         found = true;
9318                         break;
9319                 }
9320         }
9321
9322         if (found == false) {
9323                 /* NT treats not found as bad param... yet another bad
9324                    choice */
9325                 return WERR_INVALID_PARAM;
9326         }
9327
9328         /*
9329          * if the print job does not have a DEVMODE associated with it,
9330          * just use the one for the printer. A NULL devicemode is not
9331          *  a failure condition
9332          */
9333
9334         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9335         if (!devmode) {
9336                 result = spoolss_create_default_devmode(mem_ctx,
9337                                                 pinfo2->printername,
9338                                                 &devmode);
9339                 if (!W_ERROR_IS_OK(result)) {
9340                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9341                         return result;
9342                 }
9343         }
9344
9345         return fill_job_info2(mem_ctx,
9346                               r,
9347                               &queue[i],
9348                               i,
9349                               snum,
9350                               pinfo2,
9351                               devmode);
9352 }
9353
9354 /****************************************************************
9355  _spoolss_GetJob
9356 ****************************************************************/
9357
9358 WERROR _spoolss_GetJob(struct pipes_struct *p,
9359                        struct spoolss_GetJob *r)
9360 {
9361         WERROR result = WERR_OK;
9362         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9363         int snum;
9364         int count;
9365         print_queue_struct      *queue = NULL;
9366         print_status_struct prt_status;
9367
9368         /* that's an [in out] buffer */
9369
9370         if (!r->in.buffer && (r->in.offered != 0)) {
9371                 return WERR_INVALID_PARAM;
9372         }
9373
9374         DEBUG(5,("_spoolss_GetJob\n"));
9375
9376         *r->out.needed = 0;
9377
9378         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9379                 return WERR_BADFID;
9380         }
9381
9382         result = winreg_get_printer_internal(p->mem_ctx,
9383                                     get_session_info_system(),
9384                                     p->msg_ctx,
9385                                     lp_const_servicename(snum),
9386                                     &pinfo2);
9387         if (!W_ERROR_IS_OK(result)) {
9388                 return result;
9389         }
9390
9391         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9392
9393         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9394                      count, prt_status.status, prt_status.message));
9395
9396         switch (r->in.level) {
9397         case 1:
9398                 result = getjob_level_1(p->mem_ctx,
9399                                         queue, count, snum, pinfo2,
9400                                         r->in.job_id, &r->out.info->info1);
9401                 break;
9402         case 2:
9403                 result = getjob_level_2(p->mem_ctx,
9404                                         queue, count, snum, pinfo2,
9405                                         r->in.job_id, &r->out.info->info2);
9406                 break;
9407         default:
9408                 result = WERR_UNKNOWN_LEVEL;
9409                 break;
9410         }
9411
9412         SAFE_FREE(queue);
9413         TALLOC_FREE(pinfo2);
9414
9415         if (!W_ERROR_IS_OK(result)) {
9416                 TALLOC_FREE(r->out.info);
9417                 return result;
9418         }
9419
9420         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9421                                                                                    r->in.level);
9422         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9423
9424         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9425 }
9426
9427 /****************************************************************
9428  _spoolss_GetPrinterDataEx
9429 ****************************************************************/
9430
9431 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9432                                  struct spoolss_GetPrinterDataEx *r)
9433 {
9434
9435         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9436         const char *printer;
9437         int                     snum = 0;
9438         WERROR result = WERR_OK;
9439         DATA_BLOB blob;
9440         enum winreg_Type val_type = REG_NONE;
9441         uint8_t *val_data = NULL;
9442         uint32_t val_size = 0;
9443         struct dcerpc_binding_handle *b;
9444         TALLOC_CTX *tmp_ctx;
9445
9446         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9447
9448         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9449                 r->in.key_name, r->in.value_name));
9450
9451         /* in case of problem, return some default values */
9452
9453         *r->out.needed  = 0;
9454         *r->out.type    = REG_NONE;
9455
9456         tmp_ctx = talloc_new(p->mem_ctx);
9457         if (!tmp_ctx) {
9458                 return WERR_NOMEM;
9459         }
9460
9461         if (!Printer) {
9462                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9463                         OUR_HANDLE(r->in.handle)));
9464                 result = WERR_BADFID;
9465                 goto done;
9466         }
9467
9468         /* check to see if the keyname is valid */
9469         if (!strlen(r->in.key_name)) {
9470                 result = WERR_INVALID_PARAM;
9471                 goto done;
9472         }
9473
9474         /* Is the handle to a printer or to the server? */
9475
9476         if (Printer->printer_type == SPLHND_SERVER) {
9477
9478                 union spoolss_PrinterData data;
9479
9480                 result = getprinterdata_printer_server(tmp_ctx,
9481                                                        r->in.value_name,
9482                                                        r->out.type,
9483                                                        &data);
9484                 if (!W_ERROR_IS_OK(result)) {
9485                         goto done;
9486                 }
9487
9488                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9489                                                   *r->out.type, &data);
9490                 if (!W_ERROR_IS_OK(result)) {
9491                         goto done;
9492                 }
9493
9494                 *r->out.needed = blob.length;
9495
9496                 if (r->in.offered >= *r->out.needed) {
9497                         memcpy(r->out.data, blob.data, blob.length);
9498                 }
9499
9500                 result = WERR_OK;
9501                 goto done;
9502         }
9503
9504         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9505                 result = WERR_BADFID;
9506                 goto done;
9507         }
9508         printer = lp_const_servicename(snum);
9509
9510         result = winreg_printer_binding_handle(tmp_ctx,
9511                                                get_session_info_system(),
9512                                                p->msg_ctx,
9513                                                &b);
9514         if (!W_ERROR_IS_OK(result)) {
9515                 goto done;
9516         }
9517
9518         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9519         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9520             strequal(r->in.value_name, "ChangeId")) {
9521                 *r->out.type = REG_DWORD;
9522                 *r->out.needed = 4;
9523                 if (r->in.offered >= *r->out.needed) {
9524                         uint32_t changeid = 0;
9525
9526                         result = winreg_printer_get_changeid(tmp_ctx, b,
9527                                                              printer,
9528                                                              &changeid);
9529                         if (!W_ERROR_IS_OK(result)) {
9530                                 goto done;
9531                         }
9532
9533                         SIVAL(r->out.data, 0, changeid);
9534                         result = WERR_OK;
9535                 }
9536                 goto done;
9537         }
9538
9539         result = winreg_get_printer_dataex(tmp_ctx, b,
9540                                            printer,
9541                                            r->in.key_name,
9542                                            r->in.value_name,
9543                                            &val_type,
9544                                            &val_data,
9545                                            &val_size);
9546         if (!W_ERROR_IS_OK(result)) {
9547                 goto done;
9548         }
9549
9550         *r->out.needed = val_size;
9551         *r->out.type = val_type;
9552
9553         if (r->in.offered >= *r->out.needed) {
9554                 memcpy(r->out.data, val_data, val_size);
9555         }
9556
9557 done:
9558         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9559
9560         if (W_ERROR_IS_OK(result)) {
9561                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9562         }
9563
9564         talloc_free(tmp_ctx);
9565         return result;
9566 }
9567
9568 /****************************************************************
9569  _spoolss_SetPrinterDataEx
9570 ****************************************************************/
9571
9572 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9573                                  struct spoolss_SetPrinterDataEx *r)
9574 {
9575         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9576         int                     snum = 0;
9577         WERROR                  result = WERR_OK;
9578         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9579         char                    *oid_string;
9580         struct dcerpc_binding_handle *b;
9581         TALLOC_CTX *tmp_ctx;
9582
9583         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9584
9585         /* From MSDN documentation of SetPrinterDataEx: pass request to
9586            SetPrinterData if key is "PrinterDriverData" */
9587
9588         if (!Printer) {
9589                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9590                         OUR_HANDLE(r->in.handle)));
9591                 return WERR_BADFID;
9592         }
9593
9594         if (Printer->printer_type == SPLHND_SERVER) {
9595                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9596                         "Not implemented for server handles yet\n"));
9597                 return WERR_INVALID_PARAM;
9598         }
9599
9600         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9601                 return WERR_BADFID;
9602         }
9603
9604         /*
9605          * Access check : NT returns "access denied" if you make a
9606          * SetPrinterData call without the necessary privildge.
9607          * we were originally returning OK if nothing changed
9608          * which made Win2k issue **a lot** of SetPrinterData
9609          * when connecting to a printer  --jerry
9610          */
9611
9612         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9613                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9614                         "change denied by handle access permissions\n"));
9615                 return WERR_ACCESS_DENIED;
9616         }
9617
9618         tmp_ctx = talloc_new(p->mem_ctx);
9619         if (!tmp_ctx) {
9620                 return WERR_NOMEM;
9621         }
9622
9623         result = winreg_printer_binding_handle(tmp_ctx,
9624                                                get_session_info_system(),
9625                                                p->msg_ctx,
9626                                                &b);
9627         if (!W_ERROR_IS_OK(result)) {
9628                 goto done;
9629         }
9630
9631         result = winreg_get_printer(tmp_ctx, b,
9632                                     lp_servicename(talloc_tos(), snum),
9633                                     &pinfo2);
9634         if (!W_ERROR_IS_OK(result)) {
9635                 goto done;
9636         }
9637
9638         /* check for OID in valuename */
9639
9640         oid_string = strchr(r->in.value_name, ',');
9641         if (oid_string) {
9642                 *oid_string = '\0';
9643                 oid_string++;
9644         }
9645
9646         /* save the registry data */
9647
9648         result = winreg_set_printer_dataex(tmp_ctx, b,
9649                                            pinfo2->sharename,
9650                                            r->in.key_name,
9651                                            r->in.value_name,
9652                                            r->in.type,
9653                                            r->in.data,
9654                                            r->in.offered);
9655
9656         if (W_ERROR_IS_OK(result)) {
9657                 /* save the OID if one was specified */
9658                 if (oid_string) {
9659                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9660                                 r->in.key_name, SPOOL_OID_KEY);
9661                         if (!str) {
9662                                 result = WERR_NOMEM;
9663                                 goto done;
9664                         }
9665
9666                         /*
9667                          * I'm not checking the status here on purpose.  Don't know
9668                          * if this is right, but I'm returning the status from the
9669                          * previous set_printer_dataex() call.  I have no idea if
9670                          * this is right.    --jerry
9671                          */
9672                         winreg_set_printer_dataex(tmp_ctx, b,
9673                                                   pinfo2->sharename,
9674                                                   str,
9675                                                   r->in.value_name,
9676                                                   REG_SZ,
9677                                                   (uint8_t *) oid_string,
9678                                                   strlen(oid_string) + 1);
9679                 }
9680
9681                 result = winreg_printer_update_changeid(tmp_ctx, b,
9682                                                         lp_const_servicename(snum));
9683
9684         }
9685
9686 done:
9687         talloc_free(tmp_ctx);
9688         return result;
9689 }
9690
9691 /****************************************************************
9692  _spoolss_DeletePrinterDataEx
9693 ****************************************************************/
9694
9695 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9696                                     struct spoolss_DeletePrinterDataEx *r)
9697 {
9698         const char *printer;
9699         int             snum=0;
9700         WERROR          status = WERR_OK;
9701         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9702
9703         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9704
9705         if (!Printer) {
9706                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9707                         "Invalid handle (%s:%u:%u).\n",
9708                         OUR_HANDLE(r->in.handle)));
9709                 return WERR_BADFID;
9710         }
9711
9712         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9713                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9714                         "printer properties change denied by handle\n"));
9715                 return WERR_ACCESS_DENIED;
9716         }
9717
9718         if (!r->in.value_name || !r->in.key_name) {
9719                 return WERR_NOMEM;
9720         }
9721
9722         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9723                 return WERR_BADFID;
9724         }
9725         printer = lp_const_servicename(snum);
9726
9727         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9728                                               get_session_info_system(),
9729                                               p->msg_ctx,
9730                                               printer,
9731                                               r->in.key_name,
9732                                               r->in.value_name);
9733         if (W_ERROR_IS_OK(status)) {
9734                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9735                                                         get_session_info_system(),
9736                                                         p->msg_ctx,
9737                                                         printer);
9738         }
9739
9740         return status;
9741 }
9742
9743 /****************************************************************
9744  _spoolss_EnumPrinterKey
9745 ****************************************************************/
9746
9747 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9748                                struct spoolss_EnumPrinterKey *r)
9749 {
9750         uint32_t        num_keys;
9751         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9752         int             snum = 0;
9753         WERROR          result = WERR_BADFILE;
9754         const char **array = NULL;
9755         DATA_BLOB blob;
9756
9757         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9758
9759         if (!Printer) {
9760                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9761                         OUR_HANDLE(r->in.handle)));
9762                 return WERR_BADFID;
9763         }
9764
9765         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9766                 return WERR_BADFID;
9767         }
9768
9769         result = winreg_enum_printer_key_internal(p->mem_ctx,
9770                                          get_session_info_system(),
9771                                          p->msg_ctx,
9772                                          lp_const_servicename(snum),
9773                                          r->in.key_name,
9774                                          &num_keys,
9775                                          &array);
9776         if (!W_ERROR_IS_OK(result)) {
9777                 goto done;
9778         }
9779
9780         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9781                 result = WERR_NOMEM;
9782                 goto done;
9783         }
9784
9785         *r->out._ndr_size = r->in.offered / 2;
9786         *r->out.needed = blob.length;
9787
9788         if (r->in.offered < *r->out.needed) {
9789                 result = WERR_MORE_DATA;
9790         } else {
9791                 result = WERR_OK;
9792                 r->out.key_buffer->string_array = array;
9793         }
9794
9795  done:
9796         if (!W_ERROR_IS_OK(result)) {
9797                 TALLOC_FREE(array);
9798                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9799                         *r->out.needed = 0;
9800                 }
9801         }
9802
9803         return result;
9804 }
9805
9806 /****************************************************************
9807  _spoolss_DeletePrinterKey
9808 ****************************************************************/
9809
9810 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9811                                  struct spoolss_DeletePrinterKey *r)
9812 {
9813         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9814         int                     snum=0;
9815         WERROR                  status;
9816         const char *printer;
9817         struct dcerpc_binding_handle *b;
9818         TALLOC_CTX *tmp_ctx;
9819
9820         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9821
9822         if (!Printer) {
9823                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9824                         OUR_HANDLE(r->in.handle)));
9825                 return WERR_BADFID;
9826         }
9827
9828         /* if keyname == NULL, return error */
9829         if ( !r->in.key_name )
9830                 return WERR_INVALID_PARAM;
9831
9832         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9833                 return WERR_BADFID;
9834         }
9835
9836         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9837                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9838                         "printer properties change denied by handle\n"));
9839                 return WERR_ACCESS_DENIED;
9840         }
9841
9842         printer = lp_const_servicename(snum);
9843
9844         tmp_ctx = talloc_new(p->mem_ctx);
9845         if (!tmp_ctx) {
9846                 return WERR_NOMEM;
9847         }
9848
9849         status = winreg_printer_binding_handle(tmp_ctx,
9850                                                get_session_info_system(),
9851                                                p->msg_ctx,
9852                                                &b);
9853         if (!W_ERROR_IS_OK(status)) {
9854                 goto done;
9855         }
9856
9857         /* delete the key and all subkeys */
9858         status = winreg_delete_printer_key(tmp_ctx, b,
9859                                            printer,
9860                                            r->in.key_name);
9861         if (W_ERROR_IS_OK(status)) {
9862                 status = winreg_printer_update_changeid(tmp_ctx, b,
9863                                                         printer);
9864         }
9865
9866 done:
9867         talloc_free(tmp_ctx);
9868         return status;
9869 }
9870
9871 /****************************************************************
9872  _spoolss_EnumPrinterDataEx
9873 ****************************************************************/
9874
9875 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9876                                   struct spoolss_EnumPrinterDataEx *r)
9877 {
9878         uint32_t        count = 0;
9879         struct spoolss_PrinterEnumValues *info = NULL;
9880         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9881         int             snum;
9882         WERROR          result;
9883
9884         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9885
9886         *r->out.count = 0;
9887         *r->out.needed = 0;
9888         *r->out.info = NULL;
9889
9890         if (!Printer) {
9891                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9892                         OUR_HANDLE(r->in.handle)));
9893                 return WERR_BADFID;
9894         }
9895
9896         /*
9897          * first check for a keyname of NULL or "".  Win2k seems to send
9898          * this a lot and we should send back WERR_INVALID_PARAM
9899          * no need to spend time looking up the printer in this case.
9900          * --jerry
9901          */
9902
9903         if (!strlen(r->in.key_name)) {
9904                 result = WERR_INVALID_PARAM;
9905                 goto done;
9906         }
9907
9908         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9909                 return WERR_BADFID;
9910         }
9911
9912         /* now look for a match on the key name */
9913         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9914                                             get_session_info_system(),
9915                                             p->msg_ctx,
9916                                             lp_const_servicename(snum),
9917                                             r->in.key_name,
9918                                             &count,
9919                                             &info);
9920         if (!W_ERROR_IS_OK(result)) {
9921                 goto done;
9922         }
9923
9924 #if 0 /* FIXME - gd */
9925         /* housekeeping information in the reply */
9926
9927         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9928          * the hand marshalled container size is a multiple
9929          * of 4 bytes for RPC alignment.
9930          */
9931
9932         if (needed % 4) {
9933                 needed += 4-(needed % 4);
9934         }
9935 #endif
9936         *r->out.count   = count;
9937         *r->out.info    = info;
9938
9939  done:
9940         if (!W_ERROR_IS_OK(result)) {
9941                 return result;
9942         }
9943
9944         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9945                                                spoolss_EnumPrinterDataEx,
9946                                                *r->out.info,
9947                                                *r->out.count);
9948         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9949         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9950
9951         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9952 }
9953
9954 /****************************************************************************
9955 ****************************************************************************/
9956
9957 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9958                                                  const char *servername,
9959                                                  const char *environment,
9960                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9961 {
9962         WERROR werr;
9963         char *path = NULL;
9964
9965         werr = compose_spoolss_server_path(mem_ctx,
9966                                            servername,
9967                                            environment,
9968                                            SPOOLSS_PRTPROCS_PATH,
9969                                            &path);
9970         if (!W_ERROR_IS_OK(werr)) {
9971                 return werr;
9972         }
9973
9974         DEBUG(4,("print processor directory: [%s]\n", path));
9975
9976         r->directory_name = path;
9977
9978         return WERR_OK;
9979 }
9980
9981 /****************************************************************
9982  _spoolss_GetPrintProcessorDirectory
9983 ****************************************************************/
9984
9985 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9986                                            struct spoolss_GetPrintProcessorDirectory *r)
9987 {
9988         WERROR result;
9989         char *prnproc_share = NULL;
9990         bool prnproc_share_exists = false;
9991         int snum;
9992
9993         /* that's an [in out] buffer */
9994
9995         if (!r->in.buffer && (r->in.offered != 0)) {
9996                 return WERR_INVALID_PARAM;
9997         }
9998
9999         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10000                 r->in.level));
10001
10002         *r->out.needed = 0;
10003
10004         /* r->in.level is ignored */
10005
10006         /* We always should reply with a local print processor directory so that
10007          * users are not forced to have a [prnproc$] share on the Samba spoolss
10008          * server, if users decide to do so, lets announce it though - Guenther */
10009
10010         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10011         if (!prnproc_share) {
10012                 return WERR_NOMEM;
10013         }
10014         if (snum != -1) {
10015                 prnproc_share_exists = true;
10016         }
10017
10018         result = getprintprocessordirectory_level_1(p->mem_ctx,
10019                                                     prnproc_share_exists ? r->in.server : NULL,
10020                                                     r->in.environment,
10021                                                     &r->out.info->info1);
10022         if (!W_ERROR_IS_OK(result)) {
10023                 TALLOC_FREE(r->out.info);
10024                 return result;
10025         }
10026
10027         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10028                                                                                    r->out.info, r->in.level);
10029         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10030
10031         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10032 }
10033
10034 /*******************************************************************
10035  ********************************************************************/
10036
10037 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10038                                const char *dllname)
10039 {
10040         enum ndr_err_code ndr_err;
10041         struct spoolss_MonitorUi ui;
10042
10043         ui.dll_name = dllname;
10044
10045         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10046                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10047         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10048                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10049         }
10050         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10051 }
10052
10053 /*******************************************************************
10054  Streams the monitor UI DLL name in UNICODE
10055 *******************************************************************/
10056
10057 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10058                                struct security_token *token, DATA_BLOB *in,
10059                                DATA_BLOB *out, uint32_t *needed)
10060 {
10061         const char *dllname = "tcpmonui.dll";
10062
10063         *needed = (strlen(dllname)+1) * 2;
10064
10065         if (out->length < *needed) {
10066                 return WERR_INSUFFICIENT_BUFFER;
10067         }
10068
10069         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10070                 return WERR_NOMEM;
10071         }
10072
10073         return WERR_OK;
10074 }
10075
10076 /*******************************************************************
10077  ********************************************************************/
10078
10079 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10080                              struct spoolss_PortData1 *port1,
10081                              const DATA_BLOB *buf)
10082 {
10083         enum ndr_err_code ndr_err;
10084         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10085                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10086         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10087                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10088         }
10089         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10090 }
10091
10092 /*******************************************************************
10093  ********************************************************************/
10094
10095 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10096                              struct spoolss_PortData2 *port2,
10097                              const DATA_BLOB *buf)
10098 {
10099         enum ndr_err_code ndr_err;
10100         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10101                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10102         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10103                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10104         }
10105         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10106 }
10107
10108 /*******************************************************************
10109  Create a new TCP/IP port
10110 *******************************************************************/
10111
10112 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10113                              struct security_token *token, DATA_BLOB *in,
10114                              DATA_BLOB *out, uint32_t *needed)
10115 {
10116         struct spoolss_PortData1 port1;
10117         struct spoolss_PortData2 port2;
10118         char *device_uri = NULL;
10119         uint32_t version;
10120
10121         const char *portname;
10122         const char *hostaddress;
10123         const char *queue;
10124         uint32_t port_number;
10125         uint32_t protocol;
10126
10127         /* peek for spoolss_PortData version */
10128
10129         if (!in || (in->length < (128 + 4))) {
10130                 return WERR_GENERAL_FAILURE;
10131         }
10132
10133         version = IVAL(in->data, 128);
10134
10135         switch (version) {
10136                 case 1:
10137                         ZERO_STRUCT(port1);
10138
10139                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10140                                 return WERR_NOMEM;
10141                         }
10142
10143                         portname        = port1.portname;
10144                         hostaddress     = port1.hostaddress;
10145                         queue           = port1.queue;
10146                         protocol        = port1.protocol;
10147                         port_number     = port1.port_number;
10148
10149                         break;
10150                 case 2:
10151                         ZERO_STRUCT(port2);
10152
10153                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10154                                 return WERR_NOMEM;
10155                         }
10156
10157                         portname        = port2.portname;
10158                         hostaddress     = port2.hostaddress;
10159                         queue           = port2.queue;
10160                         protocol        = port2.protocol;
10161                         port_number     = port2.port_number;
10162
10163                         break;
10164                 default:
10165                         DEBUG(1,("xcvtcp_addport: "
10166                                 "unknown version of port_data: %d\n", version));
10167                         return WERR_UNKNOWN_PORT;
10168         }
10169
10170         /* create the device URI and call the add_port_hook() */
10171
10172         switch (protocol) {
10173         case PROTOCOL_RAWTCP_TYPE:
10174                 device_uri = talloc_asprintf(mem_ctx,
10175                                 "socket://%s:%d/", hostaddress,
10176                                 port_number);
10177                 break;
10178
10179         case PROTOCOL_LPR_TYPE:
10180                 device_uri = talloc_asprintf(mem_ctx,
10181                         "lpr://%s/%s", hostaddress, queue );
10182                 break;
10183
10184         default:
10185                 return WERR_UNKNOWN_PORT;
10186         }
10187
10188         if (!device_uri) {
10189                 return WERR_NOMEM;
10190         }
10191
10192         return add_port_hook(mem_ctx, token, portname, device_uri);
10193 }
10194
10195 /*******************************************************************
10196 *******************************************************************/
10197
10198 struct xcv_api_table xcvtcp_cmds[] = {
10199         { "MonitorUI",  xcvtcp_monitorui },
10200         { "AddPort",    xcvtcp_addport},
10201         { NULL,         NULL }
10202 };
10203
10204 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10205                                      struct security_token *token, const char *command,
10206                                      DATA_BLOB *inbuf,
10207                                      DATA_BLOB *outbuf,
10208                                      uint32_t *needed )
10209 {
10210         int i;
10211
10212         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10213
10214         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10215                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10216                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10217         }
10218
10219         return WERR_BADFUNC;
10220 }
10221
10222 /*******************************************************************
10223 *******************************************************************/
10224 #if 0   /* don't support management using the "Local Port" monitor */
10225
10226 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10227                                  struct security_token *token, DATA_BLOB *in,
10228                                  DATA_BLOB *out, uint32_t *needed)
10229 {
10230         const char *dllname = "localui.dll";
10231
10232         *needed = (strlen(dllname)+1) * 2;
10233
10234         if (out->length < *needed) {
10235                 return WERR_INSUFFICIENT_BUFFER;
10236         }
10237
10238         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10239                 return WERR_NOMEM;
10240         }
10241
10242         return WERR_OK;
10243 }
10244
10245 /*******************************************************************
10246 *******************************************************************/
10247
10248 struct xcv_api_table xcvlocal_cmds[] = {
10249         { "MonitorUI",  xcvlocal_monitorui },
10250         { NULL,         NULL }
10251 };
10252 #else
10253 struct xcv_api_table xcvlocal_cmds[] = {
10254         { NULL,         NULL }
10255 };
10256 #endif
10257
10258
10259
10260 /*******************************************************************
10261 *******************************************************************/
10262
10263 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10264                                        struct security_token *token, const char *command,
10265                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10266                                        uint32_t *needed)
10267 {
10268         int i;
10269
10270         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10271
10272         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10273                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10274                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10275         }
10276         return WERR_BADFUNC;
10277 }
10278
10279 /****************************************************************
10280  _spoolss_XcvData
10281 ****************************************************************/
10282
10283 WERROR _spoolss_XcvData(struct pipes_struct *p,
10284                         struct spoolss_XcvData *r)
10285 {
10286         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10287         DATA_BLOB out_data = data_blob_null;
10288         WERROR werror;
10289
10290         if (!Printer) {
10291                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10292                         OUR_HANDLE(r->in.handle)));
10293                 return WERR_BADFID;
10294         }
10295
10296         /* Has to be a handle to the TCP/IP port monitor */
10297
10298         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10299                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10300                 return WERR_BADFID;
10301         }
10302
10303         /* requires administrative access to the server */
10304
10305         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10306                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10307                 return WERR_ACCESS_DENIED;
10308         }
10309
10310         /* Allocate the outgoing buffer */
10311
10312         if (r->in.out_data_size) {
10313                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10314                 if (out_data.data == NULL) {
10315                         return WERR_NOMEM;
10316                 }
10317         }
10318
10319         switch ( Printer->printer_type ) {
10320         case SPLHND_PORTMON_TCP:
10321                 werror = process_xcvtcp_command(p->mem_ctx,
10322                                                 p->session_info->security_token,
10323                                                 r->in.function_name,
10324                                                 &r->in.in_data, &out_data,
10325                                                 r->out.needed);
10326                 break;
10327         case SPLHND_PORTMON_LOCAL:
10328                 werror = process_xcvlocal_command(p->mem_ctx,
10329                                                   p->session_info->security_token,
10330                                                   r->in.function_name,
10331                                                   &r->in.in_data, &out_data,
10332                                                   r->out.needed);
10333                 break;
10334         default:
10335                 werror = WERR_INVALID_PRINT_MONITOR;
10336         }
10337
10338         if (!W_ERROR_IS_OK(werror)) {
10339                 return werror;
10340         }
10341
10342         *r->out.status_code = 0;
10343
10344         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10345                 memcpy(r->out.out_data, out_data.data,
10346                         MIN(r->in.out_data_size, out_data.length));
10347         }
10348
10349         return WERR_OK;
10350 }
10351
10352 /****************************************************************
10353  _spoolss_AddPrintProcessor
10354 ****************************************************************/
10355
10356 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10357                                   struct spoolss_AddPrintProcessor *r)
10358 {
10359         /* for now, just indicate success and ignore the add.  We'll
10360            automatically set the winprint processor for printer
10361            entries later.  Used to debug the LexMark Optra S 1855 PCL
10362            driver --jerry */
10363
10364         return WERR_OK;
10365 }
10366
10367 /****************************************************************
10368  _spoolss_AddPort
10369 ****************************************************************/
10370
10371 WERROR _spoolss_AddPort(struct pipes_struct *p,
10372                         struct spoolss_AddPort *r)
10373 {
10374         /* do what w2k3 does */
10375
10376         return WERR_NOT_SUPPORTED;
10377 }
10378
10379 /****************************************************************
10380  _spoolss_GetPrinterDriver
10381 ****************************************************************/
10382
10383 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10384                                  struct spoolss_GetPrinterDriver *r)
10385 {
10386         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10387         return WERR_NOT_SUPPORTED;
10388 }
10389
10390 /****************************************************************
10391  _spoolss_ReadPrinter
10392 ****************************************************************/
10393
10394 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10395                             struct spoolss_ReadPrinter *r)
10396 {
10397         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10398         return WERR_NOT_SUPPORTED;
10399 }
10400
10401 /****************************************************************
10402  _spoolss_WaitForPrinterChange
10403 ****************************************************************/
10404
10405 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10406                                      struct spoolss_WaitForPrinterChange *r)
10407 {
10408         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10409         return WERR_NOT_SUPPORTED;
10410 }
10411
10412 /****************************************************************
10413  _spoolss_ConfigurePort
10414 ****************************************************************/
10415
10416 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10417                               struct spoolss_ConfigurePort *r)
10418 {
10419         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10420         return WERR_NOT_SUPPORTED;
10421 }
10422
10423 /****************************************************************
10424  _spoolss_DeletePort
10425 ****************************************************************/
10426
10427 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10428                            struct spoolss_DeletePort *r)
10429 {
10430         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10431         return WERR_NOT_SUPPORTED;
10432 }
10433
10434 /****************************************************************
10435  _spoolss_CreatePrinterIC
10436 ****************************************************************/
10437
10438 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10439                                 struct spoolss_CreatePrinterIC *r)
10440 {
10441         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10442         return WERR_NOT_SUPPORTED;
10443 }
10444
10445 /****************************************************************
10446  _spoolss_PlayGDIScriptOnPrinterIC
10447 ****************************************************************/
10448
10449 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10450                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10451 {
10452         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10453         return WERR_NOT_SUPPORTED;
10454 }
10455
10456 /****************************************************************
10457  _spoolss_DeletePrinterIC
10458 ****************************************************************/
10459
10460 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10461                                 struct spoolss_DeletePrinterIC *r)
10462 {
10463         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10464         return WERR_NOT_SUPPORTED;
10465 }
10466
10467 /****************************************************************
10468  _spoolss_AddPrinterConnection
10469 ****************************************************************/
10470
10471 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10472                                      struct spoolss_AddPrinterConnection *r)
10473 {
10474         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10475         return WERR_NOT_SUPPORTED;
10476 }
10477
10478 /****************************************************************
10479  _spoolss_DeletePrinterConnection
10480 ****************************************************************/
10481
10482 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10483                                         struct spoolss_DeletePrinterConnection *r)
10484 {
10485         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10486         return WERR_NOT_SUPPORTED;
10487 }
10488
10489 /****************************************************************
10490  _spoolss_PrinterMessageBox
10491 ****************************************************************/
10492
10493 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10494                                   struct spoolss_PrinterMessageBox *r)
10495 {
10496         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10497         return WERR_NOT_SUPPORTED;
10498 }
10499
10500 /****************************************************************
10501  _spoolss_AddMonitor
10502 ****************************************************************/
10503
10504 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10505                            struct spoolss_AddMonitor *r)
10506 {
10507         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10508         return WERR_NOT_SUPPORTED;
10509 }
10510
10511 /****************************************************************
10512  _spoolss_DeleteMonitor
10513 ****************************************************************/
10514
10515 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10516                               struct spoolss_DeleteMonitor *r)
10517 {
10518         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10519         return WERR_NOT_SUPPORTED;
10520 }
10521
10522 /****************************************************************
10523  _spoolss_DeletePrintProcessor
10524 ****************************************************************/
10525
10526 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10527                                      struct spoolss_DeletePrintProcessor *r)
10528 {
10529         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10530         return WERR_NOT_SUPPORTED;
10531 }
10532
10533 /****************************************************************
10534  _spoolss_AddPrintProvidor
10535 ****************************************************************/
10536
10537 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10538                                  struct spoolss_AddPrintProvidor *r)
10539 {
10540         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10541         return WERR_NOT_SUPPORTED;
10542 }
10543
10544 /****************************************************************
10545  _spoolss_DeletePrintProvidor
10546 ****************************************************************/
10547
10548 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10549                                     struct spoolss_DeletePrintProvidor *r)
10550 {
10551         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10552         return WERR_NOT_SUPPORTED;
10553 }
10554
10555 /****************************************************************
10556  _spoolss_FindFirstPrinterChangeNotification
10557 ****************************************************************/
10558
10559 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10560                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10561 {
10562         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10563         return WERR_NOT_SUPPORTED;
10564 }
10565
10566 /****************************************************************
10567  _spoolss_FindNextPrinterChangeNotification
10568 ****************************************************************/
10569
10570 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10571                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10572 {
10573         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10574         return WERR_NOT_SUPPORTED;
10575 }
10576
10577 /****************************************************************
10578  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10579 ****************************************************************/
10580
10581 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10582                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10583 {
10584         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10585         return WERR_NOT_SUPPORTED;
10586 }
10587
10588 /****************************************************************
10589  _spoolss_ReplyOpenPrinter
10590 ****************************************************************/
10591
10592 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10593                                  struct spoolss_ReplyOpenPrinter *r)
10594 {
10595         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10596         return WERR_NOT_SUPPORTED;
10597 }
10598
10599 /****************************************************************
10600  _spoolss_RouterReplyPrinter
10601 ****************************************************************/
10602
10603 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10604                                    struct spoolss_RouterReplyPrinter *r)
10605 {
10606         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10607         return WERR_NOT_SUPPORTED;
10608 }
10609
10610 /****************************************************************
10611  _spoolss_ReplyClosePrinter
10612 ****************************************************************/
10613
10614 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10615                                   struct spoolss_ReplyClosePrinter *r)
10616 {
10617         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10618         return WERR_NOT_SUPPORTED;
10619 }
10620
10621 /****************************************************************
10622  _spoolss_AddPortEx
10623 ****************************************************************/
10624
10625 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10626                           struct spoolss_AddPortEx *r)
10627 {
10628         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10629         return WERR_NOT_SUPPORTED;
10630 }
10631
10632 /****************************************************************
10633  _spoolss_RouterFindFirstPrinterChangeNotification
10634 ****************************************************************/
10635
10636 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10637                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10638 {
10639         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10640         return WERR_NOT_SUPPORTED;
10641 }
10642
10643 /****************************************************************
10644  _spoolss_SpoolerInit
10645 ****************************************************************/
10646
10647 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10648                             struct spoolss_SpoolerInit *r)
10649 {
10650         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10651         return WERR_NOT_SUPPORTED;
10652 }
10653
10654 /****************************************************************
10655  _spoolss_ResetPrinterEx
10656 ****************************************************************/
10657
10658 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10659                                struct spoolss_ResetPrinterEx *r)
10660 {
10661         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10662         return WERR_NOT_SUPPORTED;
10663 }
10664
10665 /****************************************************************
10666  _spoolss_RouterReplyPrinterEx
10667 ****************************************************************/
10668
10669 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10670                                      struct spoolss_RouterReplyPrinterEx *r)
10671 {
10672         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10673         return WERR_NOT_SUPPORTED;
10674 }
10675
10676 /****************************************************************
10677  _spoolss_44
10678 ****************************************************************/
10679
10680 WERROR _spoolss_44(struct pipes_struct *p,
10681                    struct spoolss_44 *r)
10682 {
10683         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10684         return WERR_NOT_SUPPORTED;
10685 }
10686
10687 /****************************************************************
10688  _spoolss_SetPort
10689 ****************************************************************/
10690
10691 WERROR _spoolss_SetPort(struct pipes_struct *p,
10692                         struct spoolss_SetPort *r)
10693 {
10694         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10695         return WERR_NOT_SUPPORTED;
10696 }
10697
10698 /****************************************************************
10699  _spoolss_4a
10700 ****************************************************************/
10701
10702 WERROR _spoolss_4a(struct pipes_struct *p,
10703                    struct spoolss_4a *r)
10704 {
10705         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10706         return WERR_NOT_SUPPORTED;
10707 }
10708
10709 /****************************************************************
10710  _spoolss_4b
10711 ****************************************************************/
10712
10713 WERROR _spoolss_4b(struct pipes_struct *p,
10714                    struct spoolss_4b *r)
10715 {
10716         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10717         return WERR_NOT_SUPPORTED;
10718 }
10719
10720 /****************************************************************
10721  _spoolss_4c
10722 ****************************************************************/
10723
10724 WERROR _spoolss_4c(struct pipes_struct *p,
10725                    struct spoolss_4c *r)
10726 {
10727         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10728         return WERR_NOT_SUPPORTED;
10729 }
10730
10731 /****************************************************************
10732  _spoolss_53
10733 ****************************************************************/
10734
10735 WERROR _spoolss_53(struct pipes_struct *p,
10736                    struct spoolss_53 *r)
10737 {
10738         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10739         return WERR_NOT_SUPPORTED;
10740 }
10741
10742 /****************************************************************
10743  _spoolss_AddPerMachineConnection
10744 ****************************************************************/
10745
10746 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10747                                         struct spoolss_AddPerMachineConnection *r)
10748 {
10749         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10750         return WERR_NOT_SUPPORTED;
10751 }
10752
10753 /****************************************************************
10754  _spoolss_DeletePerMachineConnection
10755 ****************************************************************/
10756
10757 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10758                                            struct spoolss_DeletePerMachineConnection *r)
10759 {
10760         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10761         return WERR_NOT_SUPPORTED;
10762 }
10763
10764 /****************************************************************
10765  _spoolss_EnumPerMachineConnections
10766 ****************************************************************/
10767
10768 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10769                                           struct spoolss_EnumPerMachineConnections *r)
10770 {
10771         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10772         return WERR_NOT_SUPPORTED;
10773 }
10774
10775 /****************************************************************
10776  _spoolss_5a
10777 ****************************************************************/
10778
10779 WERROR _spoolss_5a(struct pipes_struct *p,
10780                    struct spoolss_5a *r)
10781 {
10782         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10783         return WERR_NOT_SUPPORTED;
10784 }
10785
10786 /****************************************************************
10787  _spoolss_5b
10788 ****************************************************************/
10789
10790 WERROR _spoolss_5b(struct pipes_struct *p,
10791                    struct spoolss_5b *r)
10792 {
10793         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10794         return WERR_NOT_SUPPORTED;
10795 }
10796
10797 /****************************************************************
10798  _spoolss_5c
10799 ****************************************************************/
10800
10801 WERROR _spoolss_5c(struct pipes_struct *p,
10802                    struct spoolss_5c *r)
10803 {
10804         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10805         return WERR_NOT_SUPPORTED;
10806 }
10807
10808 /****************************************************************
10809  _spoolss_5d
10810 ****************************************************************/
10811
10812 WERROR _spoolss_5d(struct pipes_struct *p,
10813                    struct spoolss_5d *r)
10814 {
10815         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10816         return WERR_NOT_SUPPORTED;
10817 }
10818
10819 /****************************************************************
10820  _spoolss_5e
10821 ****************************************************************/
10822
10823 WERROR _spoolss_5e(struct pipes_struct *p,
10824                    struct spoolss_5e *r)
10825 {
10826         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10827         return WERR_NOT_SUPPORTED;
10828 }
10829
10830 /****************************************************************
10831  _spoolss_5f
10832 ****************************************************************/
10833
10834 WERROR _spoolss_5f(struct pipes_struct *p,
10835                    struct spoolss_5f *r)
10836 {
10837         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10838         return WERR_NOT_SUPPORTED;
10839 }
10840
10841 /****************************************************************
10842  _spoolss_60
10843 ****************************************************************/
10844
10845 WERROR _spoolss_60(struct pipes_struct *p,
10846                    struct spoolss_60 *r)
10847 {
10848         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10849         return WERR_NOT_SUPPORTED;
10850 }
10851
10852 /****************************************************************
10853  _spoolss_61
10854 ****************************************************************/
10855
10856 WERROR _spoolss_61(struct pipes_struct *p,
10857                    struct spoolss_61 *r)
10858 {
10859         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10860         return WERR_NOT_SUPPORTED;
10861 }
10862
10863 /****************************************************************
10864  _spoolss_62
10865 ****************************************************************/
10866
10867 WERROR _spoolss_62(struct pipes_struct *p,
10868                    struct spoolss_62 *r)
10869 {
10870         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10871         return WERR_NOT_SUPPORTED;
10872 }
10873
10874 /****************************************************************
10875  _spoolss_63
10876 ****************************************************************/
10877
10878 WERROR _spoolss_63(struct pipes_struct *p,
10879                    struct spoolss_63 *r)
10880 {
10881         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10882         return WERR_NOT_SUPPORTED;
10883 }
10884
10885 /****************************************************************
10886  _spoolss_64
10887 ****************************************************************/
10888
10889 WERROR _spoolss_64(struct pipes_struct *p,
10890                    struct spoolss_64 *r)
10891 {
10892         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10893         return WERR_NOT_SUPPORTED;
10894 }
10895
10896 /****************************************************************
10897  _spoolss_65
10898 ****************************************************************/
10899
10900 WERROR _spoolss_65(struct pipes_struct *p,
10901                    struct spoolss_65 *r)
10902 {
10903         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10904         return WERR_NOT_SUPPORTED;
10905 }
10906
10907 /****************************************************************
10908  _spoolss_GetCorePrinterDrivers
10909 ****************************************************************/
10910
10911 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10912                                       struct spoolss_GetCorePrinterDrivers *r)
10913 {
10914         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10915         return WERR_NOT_SUPPORTED;
10916 }
10917
10918 /****************************************************************
10919  _spoolss_67
10920 ****************************************************************/
10921
10922 WERROR _spoolss_67(struct pipes_struct *p,
10923                    struct spoolss_67 *r)
10924 {
10925         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10926         return WERR_NOT_SUPPORTED;
10927 }
10928
10929 /****************************************************************
10930  _spoolss_GetPrinterDriverPackagePath
10931 ****************************************************************/
10932
10933 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10934                                             struct spoolss_GetPrinterDriverPackagePath *r)
10935 {
10936         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10937         return WERR_NOT_SUPPORTED;
10938 }
10939
10940 /****************************************************************
10941  _spoolss_69
10942 ****************************************************************/
10943
10944 WERROR _spoolss_69(struct pipes_struct *p,
10945                    struct spoolss_69 *r)
10946 {
10947         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10948         return WERR_NOT_SUPPORTED;
10949 }
10950
10951 /****************************************************************
10952  _spoolss_6a
10953 ****************************************************************/
10954
10955 WERROR _spoolss_6a(struct pipes_struct *p,
10956                    struct spoolss_6a *r)
10957 {
10958         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10959         return WERR_NOT_SUPPORTED;
10960 }
10961
10962 /****************************************************************
10963  _spoolss_6b
10964 ****************************************************************/
10965
10966 WERROR _spoolss_6b(struct pipes_struct *p,
10967                    struct spoolss_6b *r)
10968 {
10969         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10970         return WERR_NOT_SUPPORTED;
10971 }
10972
10973 /****************************************************************
10974  _spoolss_6c
10975 ****************************************************************/
10976
10977 WERROR _spoolss_6c(struct pipes_struct *p,
10978                    struct spoolss_6c *r)
10979 {
10980         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10981         return WERR_NOT_SUPPORTED;
10982 }
10983
10984 /****************************************************************
10985  _spoolss_6d
10986 ****************************************************************/
10987
10988 WERROR _spoolss_6d(struct pipes_struct *p,
10989                    struct spoolss_6d *r)
10990 {
10991         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10992         return WERR_NOT_SUPPORTED;
10993 }
10994
10995 /****************************************************************
10996  _spoolss_RpcGetJobNamedPropertyValue
10997 ****************************************************************/
10998
10999 WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
11000                                             struct spoolss_RpcGetJobNamedPropertyValue *r)
11001 {
11002         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11003         return WERR_NOT_SUPPORTED;
11004 }
11005
11006 /****************************************************************
11007  _spoolss_RpcSetJobNamedProperty
11008 ****************************************************************/
11009
11010 WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
11011                                        struct spoolss_RpcSetJobNamedProperty *r)
11012 {
11013         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11014         return WERR_NOT_SUPPORTED;
11015 }
11016
11017 /****************************************************************
11018  _spoolss_RpcDeleteJobNamedProperty
11019 ****************************************************************/
11020
11021 WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
11022                                           struct spoolss_RpcDeleteJobNamedProperty *r)
11023 {
11024         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11025         return WERR_NOT_SUPPORTED;
11026 }
11027
11028 /****************************************************************
11029  _spoolss_RpcEnumJobNamedProperties
11030 ****************************************************************/
11031
11032 WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
11033                                           struct spoolss_RpcEnumJobNamedProperties *r)
11034 {
11035         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11036         return WERR_NOT_SUPPORTED;
11037 }