server: remove duplicate snum_is_shared_printer()
[obnox/samba/samba-obnox.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         struct cli_state *cli;
142         uint32_t active_connections;
143 };
144
145 static struct notify_back_channel *back_channels;
146
147 /* Map generic permissions to printer object specific permissions */
148
149 const struct standard_mapping printer_std_mapping = {
150         PRINTER_READ,
151         PRINTER_WRITE,
152         PRINTER_EXECUTE,
153         PRINTER_ALL_ACCESS
154 };
155
156 /* Map generic permissions to print server object specific permissions */
157
158 const struct standard_mapping printserver_std_mapping = {
159         SERVER_READ,
160         SERVER_WRITE,
161         SERVER_EXECUTE,
162         SERVER_ALL_ACCESS
163 };
164
165 /* API table for Xcv Monitor functions */
166
167 struct xcv_api_table {
168         const char *name;
169         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
170 };
171
172 static void prune_printername_cache(void);
173
174 /********************************************************************
175  * Canonicalize servername.
176  ********************************************************************/
177
178 static const char *canon_servername(const char *servername)
179 {
180         const char *pservername = servername;
181         while (*pservername == '\\') {
182                 pservername++;
183         }
184         return pservername;
185 }
186
187 /* translate between internal status numbers and NT status numbers */
188 static int nt_printj_status(int v)
189 {
190         switch (v) {
191         case LPQ_QUEUED:
192                 return 0;
193         case LPQ_PAUSED:
194                 return JOB_STATUS_PAUSED;
195         case LPQ_SPOOLING:
196                 return JOB_STATUS_SPOOLING;
197         case LPQ_PRINTING:
198                 return JOB_STATUS_PRINTING;
199         case LPQ_ERROR:
200                 return JOB_STATUS_ERROR;
201         case LPQ_DELETING:
202                 return JOB_STATUS_DELETING;
203         case LPQ_OFFLINE:
204                 return JOB_STATUS_OFFLINE;
205         case LPQ_PAPEROUT:
206                 return JOB_STATUS_PAPEROUT;
207         case LPQ_PRINTED:
208                 return JOB_STATUS_PRINTED;
209         case LPQ_DELETED:
210                 return JOB_STATUS_DELETED;
211         case LPQ_BLOCKED:
212                 return JOB_STATUS_BLOCKED_DEVQ;
213         case LPQ_USER_INTERVENTION:
214                 return JOB_STATUS_USER_INTERVENTION;
215         }
216         return 0;
217 }
218
219 static int nt_printq_status(int v)
220 {
221         switch (v) {
222         case LPQ_PAUSED:
223                 return PRINTER_STATUS_PAUSED;
224         case LPQ_QUEUED:
225         case LPQ_SPOOLING:
226         case LPQ_PRINTING:
227                 return 0;
228         }
229         return 0;
230 }
231
232 /***************************************************************************
233  Disconnect from the client
234 ****************************************************************************/
235
236 static void srv_spoolss_replycloseprinter(int snum,
237                                           struct printer_handle *prn_hnd)
238 {
239         WERROR result;
240         NTSTATUS status;
241
242         /*
243          * Tell the specific printing tdb we no longer want messages for this printer
244          * by deregistering our PID.
245          */
246
247         if (!print_notify_deregister_pid(snum)) {
248                 DEBUG(0, ("Failed to register our pid for printer %s\n",
249                           lp_const_servicename(snum)));
250         }
251
252         /* weird if the test succeeds !!! */
253         if (prn_hnd->notify.cli_chan == NULL ||
254             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
255             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
256             prn_hnd->notify.cli_chan->active_connections == 0) {
257                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
258                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
259                 TALLOC_FREE(prn_hnd->notify.cli_chan);
260                 return;
261         }
262
263         status = dcerpc_spoolss_ReplyClosePrinter(
264                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
265                                         talloc_tos(),
266                                         &prn_hnd->notify.cli_hnd,
267                                         &result);
268         if (!NT_STATUS_IS_OK(status)) {
269                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
270                           nt_errstr(status)));
271                 result = ntstatus_to_werror(status);
272         } else if (!W_ERROR_IS_OK(result)) {
273                 DEBUG(0, ("reply_close_printer failed [%s].\n",
274                           win_errstr(result)));
275         }
276
277         /* if it's the last connection, deconnect the IPC$ share */
278         if (prn_hnd->notify.cli_chan->active_connections == 1) {
279
280                 cli_shutdown(prn_hnd->notify.cli_chan->cli);
281                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
282                 TALLOC_FREE(prn_hnd->notify.cli_chan);
283
284                 if (prn_hnd->notify.msg_ctx != NULL) {
285                         messaging_deregister(prn_hnd->notify.msg_ctx,
286                                              MSG_PRINTER_NOTIFY2, NULL);
287                 }
288         }
289
290         if (prn_hnd->notify.cli_chan) {
291                 prn_hnd->notify.cli_chan->active_connections--;
292                 prn_hnd->notify.cli_chan = NULL;
293         }
294 }
295
296 /****************************************************************************
297  Functions to free a printer entry datastruct.
298 ****************************************************************************/
299
300 static int printer_entry_destructor(struct printer_handle *Printer)
301 {
302         if (Printer->notify.cli_chan != NULL &&
303             Printer->notify.cli_chan->active_connections > 0) {
304                 int snum = -1;
305
306                 switch(Printer->printer_type) {
307                 case SPLHND_SERVER:
308                         srv_spoolss_replycloseprinter(snum, Printer);
309                         break;
310
311                 case SPLHND_PRINTER:
312                         snum = print_queue_snum(Printer->sharename);
313                         if (snum != -1) {
314                                 srv_spoolss_replycloseprinter(snum, Printer);
315                         }
316                         break;
317                 default:
318                         break;
319                 }
320         }
321
322         Printer->notify.flags=0;
323         Printer->notify.options=0;
324         Printer->notify.localmachine[0]='\0';
325         Printer->notify.printerlocal=0;
326         TALLOC_FREE(Printer->notify.option);
327         TALLOC_FREE(Printer->devmode);
328
329         /* Remove from the internal list. */
330         DLIST_REMOVE(printers_list, Printer);
331         return 0;
332 }
333
334 /****************************************************************************
335   find printer index by handle
336 ****************************************************************************/
337
338 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
339                                                         struct policy_handle *hnd)
340 {
341         struct printer_handle *find_printer = NULL;
342
343         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
344                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
345                 return NULL;
346         }
347
348         return find_printer;
349 }
350
351 /****************************************************************************
352  Close printer index by handle.
353 ****************************************************************************/
354
355 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
356 {
357         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
358
359         if (!Printer) {
360                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
361                         OUR_HANDLE(hnd)));
362                 return false;
363         }
364
365         close_policy_hnd(p, hnd);
366
367         return true;
368 }
369
370 /****************************************************************************
371  Delete a printer given a handle.
372 ****************************************************************************/
373
374 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
375                                   const char *sharename,
376                                   struct messaging_context *msg_ctx)
377 {
378         char *cmd = lp_deleteprinter_command(talloc_tos());
379         char *command = NULL;
380         int ret;
381         bool is_print_op = false;
382
383         /* can't fail if we don't try */
384
385         if ( !*cmd )
386                 return WERR_OK;
387
388         command = talloc_asprintf(ctx,
389                         "%s \"%s\"",
390                         cmd, sharename);
391         if (!command) {
392                 return WERR_NOMEM;
393         }
394         if ( token )
395                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
396
397         DEBUG(10,("Running [%s]\n", command));
398
399         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
400
401         if ( is_print_op )
402                 become_root();
403
404         if ( (ret = smbrun(command, NULL)) == 0 ) {
405                 /* Tell everyone we updated smb.conf. */
406                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
407         }
408
409         if ( is_print_op )
410                 unbecome_root();
411
412         /********** END SePrintOperatorPrivlege BLOCK **********/
413
414         DEBUGADD(10,("returned [%d]\n", ret));
415
416         TALLOC_FREE(command);
417
418         if (ret != 0)
419                 return WERR_BADFID; /* What to return here? */
420
421         return WERR_OK;
422 }
423
424 /****************************************************************************
425  Delete a printer given a handle.
426 ****************************************************************************/
427
428 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
429 {
430         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
431         WERROR result;
432
433         if (!Printer) {
434                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
435                         OUR_HANDLE(hnd)));
436                 return WERR_BADFID;
437         }
438
439         /*
440          * It turns out that Windows allows delete printer on a handle
441          * opened by an admin user, then used on a pipe handle created
442          * by an anonymous user..... but they're working on security.... riiight !
443          * JRA.
444          */
445
446         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
447                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
448                 return WERR_ACCESS_DENIED;
449         }
450
451         /* this does not need a become root since the access check has been
452            done on the handle already */
453
454         result = winreg_delete_printer_key_internal(p->mem_ctx,
455                                            get_session_info_system(),
456                                            p->msg_ctx,
457                                            Printer->sharename,
458                                            "");
459         if (!W_ERROR_IS_OK(result)) {
460                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
461                 return WERR_BADFID;
462         }
463
464         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
465                                      Printer->sharename, p->msg_ctx);
466         if (!W_ERROR_IS_OK(result)) {
467                 return result;
468         }
469         prune_printername_cache();
470         return WERR_OK;
471 }
472
473 /****************************************************************************
474  Return the snum of a printer corresponding to an handle.
475 ****************************************************************************/
476
477 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
478                              int *number, struct share_params **params)
479 {
480         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
481
482         if (!Printer) {
483                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
484                         OUR_HANDLE(hnd)));
485                 return false;
486         }
487
488         switch (Printer->printer_type) {
489                 case SPLHND_PRINTER:
490                         DEBUG(4,("short name:%s\n", Printer->sharename));
491                         *number = print_queue_snum(Printer->sharename);
492                         return (*number != -1);
493                 case SPLHND_SERVER:
494                         return false;
495                 default:
496                         return false;
497         }
498 }
499
500 /****************************************************************************
501  Set printer handle type.
502  Check if it's \\server or \\server\printer
503 ****************************************************************************/
504
505 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
506 {
507         DEBUG(3,("Setting printer type=%s\n", handlename));
508
509         /* it's a print server */
510         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
511                 DEBUGADD(4,("Printer is a print server\n"));
512                 Printer->printer_type = SPLHND_SERVER;
513         }
514         /* it's a printer (set_printer_hnd_name() will handle port monitors */
515         else {
516                 DEBUGADD(4,("Printer is a printer\n"));
517                 Printer->printer_type = SPLHND_PRINTER;
518         }
519
520         return true;
521 }
522
523 static void prune_printername_cache_fn(const char *key, const char *value,
524                                        time_t timeout, void *private_data)
525 {
526         gencache_del(key);
527 }
528
529 static void prune_printername_cache(void)
530 {
531         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
532 }
533
534 /****************************************************************************
535  Set printer handle name..  Accept names like \\server, \\server\printer,
536  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
537  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
538  XcvDataPort() interface.
539 ****************************************************************************/
540
541 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
542                                    const struct auth_session_info *session_info,
543                                    struct messaging_context *msg_ctx,
544                                    struct printer_handle *Printer,
545                                    const char *handlename)
546 {
547         int snum;
548         int n_services=lp_numservices();
549         char *aprinter;
550         const char *printername;
551         const char *servername = NULL;
552         fstring sname;
553         bool found = false;
554         struct spoolss_PrinterInfo2 *info2 = NULL;
555         WERROR result;
556         char *p;
557
558         /*
559          * Hopefully nobody names his printers like this. Maybe \ or ,
560          * are illegal in printer names even?
561          */
562         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
563         char *cache_key;
564         char *tmp;
565
566         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
567                 (unsigned long)strlen(handlename)));
568
569         aprinter = discard_const_p(char, handlename);
570         if ( *handlename == '\\' ) {
571                 servername = canon_servername(handlename);
572                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
573                         *aprinter = '\0';
574                         aprinter++;
575                 }
576                 if (!is_myname_or_ipaddr(servername)) {
577                         return WERR_INVALID_PRINTER_NAME;
578                 }
579                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
580                 if (Printer->servername == NULL) {
581                         return WERR_NOMEM;
582                 }
583         }
584
585         if (Printer->printer_type == SPLHND_SERVER) {
586                 return WERR_OK;
587         }
588
589         if (Printer->printer_type != SPLHND_PRINTER) {
590                 return WERR_INVALID_HANDLE;
591         }
592
593         DEBUGADD(5, ("searching for [%s]\n", aprinter));
594
595         p = strchr(aprinter, ',');
596         if (p != NULL) {
597                 char *p2 = p;
598                 p++;
599                 if (*p == ' ') {
600                         p++;
601                 }
602                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
603                         *p2 = '\0';
604                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
605                         *p2 = '\0';
606                 }
607         }
608
609         if (p) {
610                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
611         }
612
613         /* check for the Port Monitor Interface */
614         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
615                 Printer->printer_type = SPLHND_PORTMON_TCP;
616                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
617                 found = true;
618         }
619         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
620                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
621                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
622                 found = true;
623         }
624
625         /*
626          * With hundreds of printers, the "for" loop iterating all
627          * shares can be quite expensive, as it is done on every
628          * OpenPrinter. The loop maps "aprinter" to "sname", the
629          * result of which we cache in gencache.
630          */
631
632         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
633                                     aprinter);
634         if ((cache_key != NULL) &&
635             gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
636
637                 found = (strcmp(tmp, printer_not_found) != 0);
638                 if (!found) {
639                         DEBUG(4, ("Printer %s not found\n", aprinter));
640                         TALLOC_FREE(tmp);
641                         return WERR_INVALID_PRINTER_NAME;
642                 }
643                 fstrcpy(sname, tmp);
644                 TALLOC_FREE(tmp);
645         }
646
647         /* Search all sharenames first as this is easier than pulling
648            the printer_info_2 off of disk. Don't use find_service() since
649            that calls out to map_username() */
650
651         /* do another loop to look for printernames */
652         for (snum = 0; !found && snum < n_services; snum++) {
653                 const char *printer = lp_const_servicename(snum);
654
655                 /* no point going on if this is not a printer */
656                 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
657                         continue;
658                 }
659
660                 /* ignore [printers] share */
661                 if (strequal(printer, "printers")) {
662                         continue;
663                 }
664
665                 fstrcpy(sname, printer);
666                 if (strequal(aprinter, printer)) {
667                         found = true;
668                         break;
669                 }
670
671                 /* no point looking up the printer object if
672                    we aren't allowing printername != sharename */
673                 if (lp_force_printername(snum)) {
674                         continue;
675                 }
676
677                 result = winreg_get_printer_internal(mem_ctx,
678                                             session_info,
679                                             msg_ctx,
680                                             sname,
681                                             &info2);
682                 if ( !W_ERROR_IS_OK(result) ) {
683                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
684                                  sname, win_errstr(result)));
685                         continue;
686                 }
687
688                 printername = strrchr(info2->printername, '\\');
689                 if (printername == NULL) {
690                         printername = info2->printername;
691                 } else {
692                         printername++;
693                 }
694
695                 if (strequal(printername, aprinter)) {
696                         found = true;
697                         break;
698                 }
699
700                 DEBUGADD(10, ("printername: %s\n", printername));
701
702                 TALLOC_FREE(info2);
703         }
704
705         if ( !found ) {
706                 if (cache_key != NULL) {
707                         gencache_set(cache_key, printer_not_found,
708                                      time(NULL)+300);
709                         TALLOC_FREE(cache_key);
710                 }
711                 DEBUGADD(4,("Printer not found\n"));
712                 return WERR_INVALID_PRINTER_NAME;
713         }
714
715         if (cache_key != NULL) {
716                 gencache_set(cache_key, sname, time(NULL)+300);
717                 TALLOC_FREE(cache_key);
718         }
719
720         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
721
722         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
723
724         return WERR_OK;
725 }
726
727 /****************************************************************************
728  Find first available printer slot. creates a printer handle for you.
729  ****************************************************************************/
730
731 static WERROR open_printer_hnd(struct pipes_struct *p,
732                                struct policy_handle *hnd,
733                                const char *name,
734                                uint32_t access_granted)
735 {
736         struct printer_handle *new_printer;
737         WERROR result;
738
739         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
740
741         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
742         if (new_printer == NULL) {
743                 return WERR_NOMEM;
744         }
745         talloc_set_destructor(new_printer, printer_entry_destructor);
746
747         /* This also steals the printer_handle on the policy_handle */
748         if (!create_policy_hnd(p, hnd, new_printer)) {
749                 TALLOC_FREE(new_printer);
750                 return WERR_INVALID_HANDLE;
751         }
752
753         /* Add to the internal list. */
754         DLIST_ADD(printers_list, new_printer);
755
756         new_printer->notify.option=NULL;
757
758         if (!set_printer_hnd_printertype(new_printer, name)) {
759                 close_printer_handle(p, hnd);
760                 return WERR_INVALID_HANDLE;
761         }
762
763         result = set_printer_hnd_name(p->mem_ctx,
764                                       get_session_info_system(),
765                                       p->msg_ctx,
766                                       new_printer, name);
767         if (!W_ERROR_IS_OK(result)) {
768                 close_printer_handle(p, hnd);
769                 return result;
770         }
771
772         new_printer->access_granted = access_granted;
773
774         DEBUG(5, ("%d printer handles active\n",
775                   (int)num_pipe_handles(p)));
776
777         return WERR_OK;
778 }
779
780 /***************************************************************************
781  check to see if the client motify handle is monitoring the notification
782  given by (notify_type, notify_field).
783  **************************************************************************/
784
785 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
786                                       uint16_t notify_field)
787 {
788         return true;
789 }
790
791 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
792                                 uint16_t notify_field)
793 {
794         struct spoolss_NotifyOption *option = p->notify.option;
795         uint32_t i, j;
796
797         /*
798          * Flags should always be zero when the change notify
799          * is registered by the client's spooler.  A user Win32 app
800          * might use the flags though instead of the NOTIFY_OPTION_INFO
801          * --jerry
802          */
803
804         if (!option) {
805                 return false;
806         }
807
808         if (p->notify.flags)
809                 return is_monitoring_event_flags(
810                         p->notify.flags, notify_type, notify_field);
811
812         for (i = 0; i < option->count; i++) {
813
814                 /* Check match for notify_type */
815
816                 if (option->types[i].type != notify_type)
817                         continue;
818
819                 /* Check match for field */
820
821                 for (j = 0; j < option->types[i].count; j++) {
822                         if (option->types[i].fields[j].field == notify_field) {
823                                 return true;
824                         }
825                 }
826         }
827
828         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
829                    p->servername, p->sharename, notify_type, notify_field));
830
831         return false;
832 }
833
834 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
835         _data->data.integer[0] = _integer; \
836         _data->data.integer[1] = 0;
837
838
839 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
840         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
841         if (!_data->data.string.string) {\
842                 _data->data.string.size = 0; \
843         } \
844         _data->data.string.size = strlen_m_term(_p) * 2;
845
846 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
847         _data->data.devmode.devmode = _devmode;
848
849 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
850                                    struct tm *t,
851                                    const char **pp,
852                                    uint32_t *plen)
853 {
854         struct spoolss_Time st;
855         uint32_t len = 16;
856         char *p;
857
858         if (!init_systemtime(&st, t)) {
859                 return;
860         }
861
862         p = talloc_array(mem_ctx, char, len);
863         if (!p) {
864                 return;
865         }
866
867         /*
868          * Systemtime must be linearized as a set of UINT16's.
869          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
870          */
871
872         SSVAL(p, 0, st.year);
873         SSVAL(p, 2, st.month);
874         SSVAL(p, 4, st.day_of_week);
875         SSVAL(p, 6, st.day);
876         SSVAL(p, 8, st.hour);
877         SSVAL(p, 10, st.minute);
878         SSVAL(p, 12, st.second);
879         SSVAL(p, 14, st.millisecond);
880
881         *pp = p;
882         *plen = len;
883 }
884
885 /* Convert a notification message to a struct spoolss_Notify */
886
887 static void notify_one_value(struct spoolss_notify_msg *msg,
888                              struct spoolss_Notify *data,
889                              TALLOC_CTX *mem_ctx)
890 {
891         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
892 }
893
894 static void notify_string(struct spoolss_notify_msg *msg,
895                           struct spoolss_Notify *data,
896                           TALLOC_CTX *mem_ctx)
897 {
898         /* The length of the message includes the trailing \0 */
899
900         data->data.string.size = msg->len * 2;
901         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
902         if (!data->data.string.string) {
903                 data->data.string.size = 0;
904                 return;
905         }
906 }
907
908 static void notify_system_time(struct spoolss_notify_msg *msg,
909                                struct spoolss_Notify *data,
910                                TALLOC_CTX *mem_ctx)
911 {
912         data->data.string.string = NULL;
913         data->data.string.size = 0;
914
915         if (msg->len != sizeof(time_t)) {
916                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
917                           msg->len));
918                 return;
919         }
920
921         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
922                                &data->data.string.string,
923                                &data->data.string.size);
924 }
925
926 struct notify2_message_table {
927         const char *name;
928         void (*fn)(struct spoolss_notify_msg *msg,
929                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
930 };
931
932 static struct notify2_message_table printer_notify_table[] = {
933         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
934         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
935         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
936         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
937         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
938         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
939         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
940         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
941         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
942         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
943         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
944         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
945         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
946         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
947         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
948         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
949         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
950         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
951         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
952 };
953
954 static struct notify2_message_table job_notify_table[] = {
955         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
956         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
957         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
958         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
959         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
960         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
961         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
962         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
963         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
964         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
965         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
966         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
967         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
968         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
969         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
970         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
971         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
972         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
973         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
974         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
975         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
976         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
977         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
978         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
979 };
980
981
982 /***********************************************************************
983  Allocate talloc context for container object
984  **********************************************************************/
985
986 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
987 {
988         if ( !ctr )
989                 return;
990
991         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
992
993         return;
994 }
995
996 /***********************************************************************
997  release all allocated memory and zero out structure
998  **********************************************************************/
999
1000 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1001 {
1002         if ( !ctr )
1003                 return;
1004
1005         if ( ctr->ctx )
1006                 talloc_destroy(ctr->ctx);
1007
1008         ZERO_STRUCTP(ctr);
1009
1010         return;
1011 }
1012
1013 /***********************************************************************
1014  **********************************************************************/
1015
1016 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1017 {
1018         if ( !ctr )
1019                 return NULL;
1020
1021         return ctr->ctx;
1022 }
1023
1024 /***********************************************************************
1025  **********************************************************************/
1026
1027 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1028 {
1029         if ( !ctr || !ctr->msg_groups )
1030                 return NULL;
1031
1032         if ( idx >= ctr->num_groups )
1033                 return NULL;
1034
1035         return &ctr->msg_groups[idx];
1036
1037 }
1038
1039 /***********************************************************************
1040  How many groups of change messages do we have ?
1041  **********************************************************************/
1042
1043 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1044 {
1045         if ( !ctr )
1046                 return 0;
1047
1048         return ctr->num_groups;
1049 }
1050
1051 /***********************************************************************
1052  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1053  **********************************************************************/
1054
1055 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1056 {
1057         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1058         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1059         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1060         int                             i, new_slot;
1061
1062         if ( !ctr || !msg )
1063                 return 0;
1064
1065         /* loop over all groups looking for a matching printer name */
1066
1067         for ( i=0; i<ctr->num_groups; i++ ) {
1068                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1069                         break;
1070         }
1071
1072         /* add a new group? */
1073
1074         if ( i == ctr->num_groups ) {
1075                 ctr->num_groups++;
1076
1077                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1078                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1079                         return 0;
1080                 }
1081                 ctr->msg_groups = groups;
1082
1083                 /* clear the new entry and set the printer name */
1084
1085                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1086                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1087         }
1088
1089         /* add the change messages; 'i' is the correct index now regardless */
1090
1091         msg_grp = &ctr->msg_groups[i];
1092
1093         msg_grp->num_msgs++;
1094
1095         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1096                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1097                 return 0;
1098         }
1099         msg_grp->msgs = msg_list;
1100
1101         new_slot = msg_grp->num_msgs-1;
1102         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1103
1104         /* need to allocate own copy of data */
1105
1106         if ( msg->len != 0 )
1107                 msg_grp->msgs[new_slot].notify.data = (char *)
1108                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1109
1110         return ctr->num_groups;
1111 }
1112
1113 static void construct_info_data(struct spoolss_Notify *info_data,
1114                                 enum spoolss_NotifyType type,
1115                                 uint16_t field, int id);
1116
1117 /***********************************************************************
1118  Send a change notication message on all handles which have a call
1119  back registered
1120  **********************************************************************/
1121
1122 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1123                                   struct printer_handle *prn_hnd,
1124                                   SPOOLSS_NOTIFY_MSG *messages,
1125                                   uint32_t num_msgs,
1126                                   struct spoolss_Notify **_notifies,
1127                                   int *_count)
1128 {
1129         struct spoolss_Notify *notifies;
1130         SPOOLSS_NOTIFY_MSG *msg;
1131         int count = 0;
1132         uint32_t id;
1133         int i;
1134
1135         notifies = talloc_zero_array(mem_ctx,
1136                                      struct spoolss_Notify, num_msgs);
1137         if (!notifies) {
1138                 return ENOMEM;
1139         }
1140
1141         for (i = 0; i < num_msgs; i++) {
1142
1143                 msg = &messages[i];
1144
1145                 /* Are we monitoring this event? */
1146
1147                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1148                         continue;
1149                 }
1150
1151                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1152                            "for printer [%s]\n",
1153                            msg->type, msg->field, prn_hnd->sharename));
1154
1155                 /*
1156                  * if the is a printer notification handle and not a job
1157                  * notification type, then set the id to 0.
1158                  * Otherwise just use what was specified in the message.
1159                  *
1160                  * When registering change notification on a print server
1161                  * handle we always need to send back the id (snum) matching
1162                  * the printer for which the change took place.
1163                  * For change notify registered on a printer handle,
1164                  * this does not matter and the id should be 0.
1165                  *
1166                  * --jerry
1167                  */
1168
1169                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1170                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1171                         id = 0;
1172                 } else {
1173                         id = msg->id;
1174                 }
1175
1176                 /* Convert unix jobid to smb jobid */
1177
1178                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1179                         id = sysjob_to_jobid(msg->id);
1180
1181                         if (id == -1) {
1182                                 DEBUG(3, ("no such unix jobid %d\n",
1183                                           msg->id));
1184                                 continue;
1185                         }
1186                 }
1187
1188                 construct_info_data(&notifies[count],
1189                                     msg->type, msg->field, id);
1190
1191                 switch(msg->type) {
1192                 case PRINTER_NOTIFY_TYPE:
1193                         if (printer_notify_table[msg->field].fn) {
1194                                 printer_notify_table[msg->field].fn(msg,
1195                                                 &notifies[count], mem_ctx);
1196                         }
1197                         break;
1198
1199                 case JOB_NOTIFY_TYPE:
1200                         if (job_notify_table[msg->field].fn) {
1201                                 job_notify_table[msg->field].fn(msg,
1202                                                 &notifies[count], mem_ctx);
1203                         }
1204                         break;
1205
1206                 default:
1207                         DEBUG(5, ("Unknown notification type %d\n",
1208                                   msg->type));
1209                         continue;
1210                 }
1211
1212                 count++;
1213         }
1214
1215         *_notifies = notifies;
1216         *_count = count;
1217
1218         return 0;
1219 }
1220
1221 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1222                                 struct printer_handle *prn_hnd,
1223                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1224 {
1225         struct spoolss_Notify *notifies;
1226         int count = 0;
1227         union spoolss_ReplyPrinterInfo info;
1228         struct spoolss_NotifyInfo info0;
1229         uint32_t reply_result;
1230         NTSTATUS status;
1231         WERROR werr;
1232         int ret;
1233
1234         /* Is there notification on this handle? */
1235         if (prn_hnd->notify.cli_chan == NULL ||
1236             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1237             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1238             prn_hnd->notify.cli_chan->active_connections == 0) {
1239                 return 0;
1240         }
1241
1242         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1243                    prn_hnd->servername, prn_hnd->sharename));
1244
1245         /* For this printer? Print servers always receive notifications. */
1246         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1247             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1248                 return 0;
1249         }
1250
1251         DEBUG(10,("Our printer\n"));
1252
1253         /* build the array of change notifications */
1254         ret = build_notify2_messages(mem_ctx, prn_hnd,
1255                                      msg_group->msgs,
1256                                      msg_group->num_msgs,
1257                                      &notifies, &count);
1258         if (ret) {
1259                 return ret;
1260         }
1261
1262         info0.version   = 0x2;
1263         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1264         info0.count     = count;
1265         info0.notifies  = notifies;
1266
1267         info.info0 = &info0;
1268
1269         status = dcerpc_spoolss_RouterReplyPrinterEx(
1270                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1271                                 mem_ctx,
1272                                 &prn_hnd->notify.cli_hnd,
1273                                 prn_hnd->notify.change, /* color */
1274                                 prn_hnd->notify.flags,
1275                                 &reply_result,
1276                                 0, /* reply_type, must be 0 */
1277                                 info, &werr);
1278         if (!NT_STATUS_IS_OK(status)) {
1279                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1280                           "failed: %s\n",
1281                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1282                           nt_errstr(status)));
1283                 werr = ntstatus_to_werror(status);
1284         } else if (!W_ERROR_IS_OK(werr)) {
1285                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1286                           "failed: %s\n",
1287                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1288                           win_errstr(werr)));
1289         }
1290         switch (reply_result) {
1291         case 0:
1292                 break;
1293         case PRINTER_NOTIFY_INFO_DISCARDED:
1294         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1295         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1296                 break;
1297         default:
1298                 break;
1299         }
1300
1301         return 0;
1302 }
1303
1304 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1305 {
1306         struct printer_handle    *p;
1307         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1308         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1309         int ret;
1310
1311         if ( !msg_group ) {
1312                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1313                 return;
1314         }
1315
1316         if (!msg_group->msgs) {
1317                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1318                 return;
1319         }
1320
1321         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1322
1323         /* loop over all printers */
1324
1325         for (p = printers_list; p; p = p->next) {
1326                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1327                 if (ret) {
1328                         goto done;
1329                 }
1330         }
1331
1332 done:
1333         DEBUG(8,("send_notify2_changes: Exit...\n"));
1334         return;
1335 }
1336
1337 /***********************************************************************
1338  **********************************************************************/
1339
1340 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1341 {
1342
1343         uint32_t tv_sec, tv_usec;
1344         size_t offset = 0;
1345
1346         /* Unpack message */
1347
1348         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1349                              msg->printer);
1350
1351         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1352                                 &tv_sec, &tv_usec,
1353                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1354
1355         if (msg->len == 0)
1356                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1357                            &msg->notify.value[0], &msg->notify.value[1]);
1358         else
1359                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1360                            &msg->len, &msg->notify.data);
1361
1362         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1363                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1364
1365         tv->tv_sec = tv_sec;
1366         tv->tv_usec = tv_usec;
1367
1368         if (msg->len == 0)
1369                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1370                           msg->notify.value[1]));
1371         else
1372                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1373
1374         return true;
1375 }
1376
1377 /********************************************************************
1378  Receive a notify2 message list
1379  ********************************************************************/
1380
1381 static void receive_notify2_message_list(struct messaging_context *msg,
1382                                          void *private_data,
1383                                          uint32_t msg_type,
1384                                          struct server_id server_id,
1385                                          DATA_BLOB *data)
1386 {
1387         size_t                  msg_count, i;
1388         char                    *buf = (char *)data->data;
1389         char                    *msg_ptr;
1390         size_t                  msg_len;
1391         SPOOLSS_NOTIFY_MSG      notify;
1392         SPOOLSS_NOTIFY_MSG_CTR  messages;
1393         int                     num_groups;
1394
1395         if (data->length < 4) {
1396                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1397                 return;
1398         }
1399
1400         msg_count = IVAL(buf, 0);
1401         msg_ptr = buf + 4;
1402
1403         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1404
1405         if (msg_count == 0) {
1406                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1407                 return;
1408         }
1409
1410         /* initialize the container */
1411
1412         ZERO_STRUCT( messages );
1413         notify_msg_ctr_init( &messages );
1414
1415         /*
1416          * build message groups for each printer identified
1417          * in a change_notify msg.  Remember that a PCN message
1418          * includes the handle returned for the srv_spoolss_replyopenprinter()
1419          * call.  Therefore messages are grouped according to printer handle.
1420          */
1421
1422         for ( i=0; i<msg_count; i++ ) {
1423                 struct timeval msg_tv;
1424
1425                 if (msg_ptr + 4 - buf > data->length) {
1426                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1427                         return;
1428                 }
1429
1430                 msg_len = IVAL(msg_ptr,0);
1431                 msg_ptr += 4;
1432
1433                 if (msg_ptr + msg_len - buf > data->length) {
1434                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1435                         return;
1436                 }
1437
1438                 /* unpack messages */
1439
1440                 ZERO_STRUCT( notify );
1441                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1442                 msg_ptr += msg_len;
1443
1444                 /* add to correct list in container */
1445
1446                 notify_msg_ctr_addmsg( &messages, &notify );
1447
1448                 /* free memory that might have been allocated by notify2_unpack_msg() */
1449
1450                 if ( notify.len != 0 )
1451                         SAFE_FREE( notify.notify.data );
1452         }
1453
1454         /* process each group of messages */
1455
1456         num_groups = notify_msg_ctr_numgroups( &messages );
1457         for ( i=0; i<num_groups; i++ )
1458                 send_notify2_changes( &messages, i );
1459
1460
1461         /* cleanup */
1462
1463         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1464                 (uint32_t)msg_count ));
1465
1466         notify_msg_ctr_destroy( &messages );
1467
1468         return;
1469 }
1470
1471 /********************************************************************
1472  Send a message to ourself about new driver being installed
1473  so we can upgrade the information for each printer bound to this
1474  driver
1475  ********************************************************************/
1476
1477 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1478                                             struct messaging_context *msg_ctx)
1479 {
1480         int len = strlen(drivername);
1481
1482         if (!len)
1483                 return false;
1484
1485         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1486                 drivername));
1487
1488         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1489                            MSG_PRINTER_DRVUPGRADE,
1490                            (const uint8_t *)drivername, len+1);
1491
1492         return true;
1493 }
1494
1495 void srv_spoolss_cleanup(void)
1496 {
1497         struct printer_session_counter *session_counter;
1498
1499         for (session_counter = counter_list;
1500              session_counter != NULL;
1501              session_counter = counter_list) {
1502                 DLIST_REMOVE(counter_list, session_counter);
1503                 TALLOC_FREE(session_counter);
1504         }
1505 }
1506
1507 /**********************************************************************
1508  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1509  over all printers, upgrading ones as necessary
1510  This is now *ONLY* called inside the background lpq updater. JRA.
1511  **********************************************************************/
1512
1513 void do_drv_upgrade_printer(struct messaging_context *msg,
1514                             void *private_data,
1515                             uint32_t msg_type,
1516                             struct server_id server_id,
1517                             DATA_BLOB *data)
1518 {
1519         TALLOC_CTX *tmp_ctx;
1520         const struct auth_session_info *session_info = get_session_info_system();
1521         struct spoolss_PrinterInfo2 *pinfo2;
1522         WERROR result;
1523         const char *drivername;
1524         int snum;
1525         int n_services = lp_numservices();
1526         struct dcerpc_binding_handle *b = NULL;
1527
1528         tmp_ctx = talloc_new(NULL);
1529         if (!tmp_ctx) return;
1530
1531         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1532         if (!drivername) {
1533                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1534                 goto done;
1535         }
1536
1537         DEBUG(10, ("do_drv_upgrade_printer: "
1538                    "Got message for new driver [%s]\n", drivername));
1539
1540         /* Iterate the printer list */
1541
1542         for (snum = 0; snum < n_services; snum++) {
1543                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1544                         continue;
1545                 }
1546
1547                 /* ignore [printers] share */
1548                 if (strequal(lp_const_servicename(snum), "printers")) {
1549                         continue;
1550                 }
1551
1552                 if (b == NULL) {
1553                         result = winreg_printer_binding_handle(tmp_ctx,
1554                                                                session_info,
1555                                                                msg,
1556                                                                &b);
1557                         if (!W_ERROR_IS_OK(result)) {
1558                                 break;
1559                         }
1560                 }
1561
1562                 result = winreg_get_printer(tmp_ctx, b,
1563                                             lp_const_servicename(snum),
1564                                             &pinfo2);
1565
1566                 if (!W_ERROR_IS_OK(result)) {
1567                         continue;
1568                 }
1569
1570                 if (!pinfo2->drivername) {
1571                         continue;
1572                 }
1573
1574                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1575                         continue;
1576                 }
1577
1578                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1579
1580                 /* all we care about currently is the change_id */
1581                 result = winreg_printer_update_changeid(tmp_ctx, b,
1582                                                         pinfo2->printername);
1583
1584                 if (!W_ERROR_IS_OK(result)) {
1585                         DEBUG(3, ("do_drv_upgrade_printer: "
1586                                   "Failed to update changeid [%s]\n",
1587                                   win_errstr(result)));
1588                 }
1589         }
1590
1591         /* all done */
1592 done:
1593         talloc_free(tmp_ctx);
1594 }
1595
1596 /********************************************************************
1597  Update the cache for all printq's with a registered client
1598  connection
1599  ********************************************************************/
1600
1601 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1602 {
1603         struct printer_handle *printer = printers_list;
1604         int snum;
1605
1606         /* loop through all printers and update the cache where
1607            a client is connected */
1608         while (printer) {
1609                 if ((printer->printer_type == SPLHND_PRINTER) &&
1610                     ((printer->notify.cli_chan != NULL) &&
1611                      (printer->notify.cli_chan->active_connections > 0))) {
1612                         snum = print_queue_snum(printer->sharename);
1613                         print_queue_status(msg_ctx, snum, NULL, NULL);
1614                 }
1615
1616                 printer = printer->next;
1617         }
1618
1619         return;
1620 }
1621
1622 /****************************************************************
1623  _spoolss_OpenPrinter
1624 ****************************************************************/
1625
1626 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1627                             struct spoolss_OpenPrinter *r)
1628 {
1629         struct spoolss_OpenPrinterEx e;
1630         struct spoolss_UserLevel1 level1;
1631         WERROR werr;
1632
1633         ZERO_STRUCT(level1);
1634
1635         e.in.printername        = r->in.printername;
1636         e.in.datatype           = r->in.datatype;
1637         e.in.devmode_ctr        = r->in.devmode_ctr;
1638         e.in.access_mask        = r->in.access_mask;
1639         e.in.userlevel_ctr.level                = 1;
1640         e.in.userlevel_ctr.user_info.level1     = &level1;
1641
1642         e.out.handle            = r->out.handle;
1643
1644         werr = _spoolss_OpenPrinterEx(p, &e);
1645
1646         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1647                 /* OpenPrinterEx returns this for a bad
1648                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1649                  * instead.
1650                  */
1651                 werr = WERR_INVALID_PRINTER_NAME;
1652         }
1653
1654         return werr;
1655 }
1656
1657 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1658                               struct spoolss_DeviceMode *orig,
1659                               struct spoolss_DeviceMode **dest)
1660 {
1661         struct spoolss_DeviceMode *dm;
1662
1663         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1664         if (!dm) {
1665                 return WERR_NOMEM;
1666         }
1667
1668         /* copy all values, then duplicate strings and structs */
1669         *dm = *orig;
1670
1671         dm->devicename = talloc_strdup(dm, orig->devicename);
1672         if (!dm->devicename) {
1673                 return WERR_NOMEM;
1674         }
1675         dm->formname = talloc_strdup(dm, orig->formname);
1676         if (!dm->formname) {
1677                 return WERR_NOMEM;
1678         }
1679         if (orig->driverextra_data.data) {
1680                 dm->driverextra_data.data =
1681                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1682                                         orig->driverextra_data.length);
1683                 if (!dm->driverextra_data.data) {
1684                         return WERR_NOMEM;
1685                 }
1686         }
1687
1688         *dest = dm;
1689         return WERR_OK;
1690 }
1691
1692 /****************************************************************
1693  _spoolss_OpenPrinterEx
1694 ****************************************************************/
1695
1696 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1697                               struct spoolss_OpenPrinterEx *r)
1698 {
1699         int snum;
1700         char *raddr;
1701         char *rhost;
1702         struct printer_handle *Printer=NULL;
1703         WERROR result;
1704         int rc;
1705
1706         if (!r->in.printername) {
1707                 return WERR_INVALID_PARAM;
1708         }
1709
1710         if (!*r->in.printername) {
1711                 return WERR_INVALID_PARAM;
1712         }
1713
1714         if (r->in.userlevel_ctr.level > 3) {
1715                 return WERR_INVALID_PARAM;
1716         }
1717         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1718             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1719             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1720                 return WERR_INVALID_PARAM;
1721         }
1722
1723         /* some sanity check because you can open a printer or a print server */
1724         /* aka: \\server\printer or \\server */
1725
1726         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1727
1728         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1729         if (!W_ERROR_IS_OK(result)) {
1730                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1731                         "for printer %s\n", r->in.printername));
1732                 ZERO_STRUCTP(r->out.handle);
1733                 return result;
1734         }
1735
1736         Printer = find_printer_index_by_hnd(p, r->out.handle);
1737         if ( !Printer ) {
1738                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1739                         "handle we created for printer %s\n", r->in.printername));
1740                 close_printer_handle(p, r->out.handle);
1741                 ZERO_STRUCTP(r->out.handle);
1742                 return WERR_INVALID_PARAM;
1743         }
1744
1745         /*
1746          * First case: the user is opening the print server:
1747          *
1748          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1749          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1750          *
1751          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1752          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1753          * or if the user is listed in the smb.conf printer admin parameter.
1754          *
1755          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1756          * client view printer folder, but does not show the MSAPW.
1757          *
1758          * Note: this test needs code to check access rights here too. Jeremy
1759          * could you look at this?
1760          *
1761          * Second case: the user is opening a printer:
1762          * NT doesn't let us connect to a printer if the connecting user
1763          * doesn't have print permission.
1764          *
1765          * Third case: user is opening a Port Monitor
1766          * access checks same as opening a handle to the print server.
1767          */
1768
1769         switch (Printer->printer_type )
1770         {
1771         case SPLHND_SERVER:
1772         case SPLHND_PORTMON_TCP:
1773         case SPLHND_PORTMON_LOCAL:
1774                 /* Printserver handles use global struct... */
1775
1776                 snum = -1;
1777
1778                 /* Map standard access rights to object specific access rights */
1779
1780                 se_map_standard(&r->in.access_mask,
1781                                 &printserver_std_mapping);
1782
1783                 /* Deny any object specific bits that don't apply to print
1784                    servers (i.e printer and job specific bits) */
1785
1786                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1787
1788                 if (r->in.access_mask &
1789                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1790                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1791                         close_printer_handle(p, r->out.handle);
1792                         ZERO_STRUCTP(r->out.handle);
1793                         return WERR_ACCESS_DENIED;
1794                 }
1795
1796                 /* Allow admin access */
1797
1798                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1799                 {
1800                         if (!lp_show_add_printer_wizard()) {
1801                                 close_printer_handle(p, r->out.handle);
1802                                 ZERO_STRUCTP(r->out.handle);
1803                                 return WERR_ACCESS_DENIED;
1804                         }
1805
1806                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1807                            and not a printer admin, then fail */
1808
1809                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1810                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1811                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1812                                                 p->session_info->security_token)) {
1813                                 close_printer_handle(p, r->out.handle);
1814                                 ZERO_STRUCTP(r->out.handle);
1815                                 DEBUG(3,("access DENIED as user is not root, "
1816                                         "has no printoperator privilege, "
1817                                         "not a member of the printoperator builtin group and "
1818                                         "is not in printer admin list"));
1819                                 return WERR_ACCESS_DENIED;
1820                         }
1821
1822                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1823                 }
1824                 else
1825                 {
1826                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1827                 }
1828
1829                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1830                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1831
1832                 /* We fall through to return WERR_OK */
1833                 break;
1834
1835         case SPLHND_PRINTER:
1836                 /* NT doesn't let us connect to a printer if the connecting user
1837                    doesn't have print permission.  */
1838
1839                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1840                         close_printer_handle(p, r->out.handle);
1841                         ZERO_STRUCTP(r->out.handle);
1842                         return WERR_BADFID;
1843                 }
1844
1845                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1846                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1847                 }
1848
1849                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1850
1851                 /* map an empty access mask to the minimum access mask */
1852                 if (r->in.access_mask == 0x0)
1853                         r->in.access_mask = PRINTER_ACCESS_USE;
1854
1855                 /*
1856                  * If we are not serving the printer driver for this printer,
1857                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1858                  * will keep NT clients happy  --jerry
1859                  */
1860
1861                 if (lp_use_client_driver(snum)
1862                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1863                 {
1864                         r->in.access_mask = PRINTER_ACCESS_USE;
1865                 }
1866
1867                 /* check smb.conf parameters and the the sec_desc */
1868                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1869                                                          p->mem_ctx);
1870                 if (raddr == NULL) {
1871                         return WERR_NOMEM;
1872                 }
1873
1874                 rc = get_remote_hostname(p->remote_address,
1875                                          &rhost,
1876                                          p->mem_ctx);
1877                 if (rc < 0) {
1878                         return WERR_NOMEM;
1879                 }
1880                 if (strequal(rhost, "UNKNOWN")) {
1881                         rhost = raddr;
1882                 }
1883
1884                 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1885                                   rhost, raddr)) {
1886                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1887                         ZERO_STRUCTP(r->out.handle);
1888                         return WERR_ACCESS_DENIED;
1889                 }
1890
1891                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1892                                    p->session_info->security_token, snum) ||
1893                     !W_ERROR_IS_OK(print_access_check(p->session_info,
1894                                                       p->msg_ctx,
1895                                                       snum,
1896                                                       r->in.access_mask))) {
1897                         DEBUG(3, ("access DENIED for printer open\n"));
1898                         close_printer_handle(p, r->out.handle);
1899                         ZERO_STRUCTP(r->out.handle);
1900                         return WERR_ACCESS_DENIED;
1901                 }
1902
1903                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1904                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1905                         close_printer_handle(p, r->out.handle);
1906                         ZERO_STRUCTP(r->out.handle);
1907                         return WERR_ACCESS_DENIED;
1908                 }
1909
1910                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1911                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1912                 else
1913                         r->in.access_mask = PRINTER_ACCESS_USE;
1914
1915                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1916                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1917
1918                 winreg_create_printer_internal(p->mem_ctx,
1919                                       get_session_info_system(),
1920                                       p->msg_ctx,
1921                                       lp_const_servicename(snum));
1922
1923                 break;
1924
1925         default:
1926                 /* sanity check to prevent programmer error */
1927                 ZERO_STRUCTP(r->out.handle);
1928                 return WERR_BADFID;
1929         }
1930
1931         Printer->access_granted = r->in.access_mask;
1932
1933         /*
1934          * If the client sent a devmode in the OpenPrinter() call, then
1935          * save it here in case we get a job submission on this handle
1936          */
1937
1938          if ((Printer->printer_type != SPLHND_SERVER)
1939           && (r->in.devmode_ctr.devmode != NULL)) {
1940                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1941                                 &Printer->devmode);
1942          }
1943
1944         return WERR_OK;
1945 }
1946
1947 /****************************************************************
1948  _spoolss_ClosePrinter
1949 ****************************************************************/
1950
1951 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1952                              struct spoolss_ClosePrinter *r)
1953 {
1954         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1955
1956         if (Printer && Printer->document_started) {
1957                 struct spoolss_EndDocPrinter e;
1958
1959                 e.in.handle = r->in.handle;
1960
1961                 _spoolss_EndDocPrinter(p, &e);
1962         }
1963
1964         if (!close_printer_handle(p, r->in.handle))
1965                 return WERR_BADFID;
1966
1967         /* clear the returned printer handle.  Observed behavior
1968            from Win2k server.  Don't think this really matters.
1969            Previous code just copied the value of the closed
1970            handle.    --jerry */
1971
1972         ZERO_STRUCTP(r->out.handle);
1973
1974         return WERR_OK;
1975 }
1976
1977 /****************************************************************
1978  _spoolss_DeletePrinter
1979 ****************************************************************/
1980
1981 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1982                               struct spoolss_DeletePrinter *r)
1983 {
1984         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1985         WERROR result;
1986         int snum;
1987
1988         if (Printer && Printer->document_started) {
1989                 struct spoolss_EndDocPrinter e;
1990
1991                 e.in.handle = r->in.handle;
1992
1993                 _spoolss_EndDocPrinter(p, &e);
1994         }
1995
1996         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1997                 winreg_delete_printer_key_internal(p->mem_ctx,
1998                                           get_session_info_system(),
1999                                           p->msg_ctx,
2000                                           lp_const_servicename(snum),
2001                                           "");
2002         }
2003
2004         result = delete_printer_handle(p, r->in.handle);
2005
2006         return result;
2007 }
2008
2009 /*******************************************************************
2010  * static function to lookup the version id corresponding to an
2011  * long architecture string
2012  ******************************************************************/
2013
2014 static const struct print_architecture_table_node archi_table[]= {
2015
2016         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2017         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2018         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2019         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2020         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2021         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2022         {"Windows x64",          SPL_ARCH_X64,          3 },
2023         {NULL,                   "",            -1 }
2024 };
2025
2026 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2027                                    SPOOLSS_DRIVER_VERSION_NT35,
2028                                    SPOOLSS_DRIVER_VERSION_NT4,
2029                                    SPOOLSS_DRIVER_VERSION_200X,
2030                                    -1};
2031
2032 static int get_version_id(const char *arch)
2033 {
2034         int i;
2035
2036         for (i=0; archi_table[i].long_archi != NULL; i++)
2037         {
2038                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2039                         return (archi_table[i].version);
2040         }
2041
2042         return -1;
2043 }
2044
2045 /****************************************************************
2046  _spoolss_DeletePrinterDriver
2047 ****************************************************************/
2048
2049 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2050                                     struct spoolss_DeletePrinterDriver *r)
2051 {
2052
2053         struct spoolss_DriverInfo8 *info = NULL;
2054         int                             version;
2055         WERROR                          status;
2056         struct dcerpc_binding_handle *b;
2057         TALLOC_CTX *tmp_ctx = NULL;
2058         int i;
2059         bool found;
2060
2061         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2062            and not a printer admin, then fail */
2063
2064         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2065             !security_token_has_privilege(p->session_info->security_token,
2066                                           SEC_PRIV_PRINT_OPERATOR)) {
2067                 return WERR_ACCESS_DENIED;
2068         }
2069
2070         /* check that we have a valid driver name first */
2071
2072         if ((version = get_version_id(r->in.architecture)) == -1) {
2073                 return WERR_INVALID_ENVIRONMENT;
2074         }
2075
2076         tmp_ctx = talloc_new(p->mem_ctx);
2077         if (!tmp_ctx) {
2078                 return WERR_NOMEM;
2079         }
2080
2081         status = winreg_printer_binding_handle(tmp_ctx,
2082                                                get_session_info_system(),
2083                                                p->msg_ctx,
2084                                                &b);
2085         if (!W_ERROR_IS_OK(status)) {
2086                 goto done;
2087         }
2088
2089         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2090                 status = winreg_get_driver(tmp_ctx, b,
2091                                            r->in.architecture, r->in.driver,
2092                                            drv_cversion[i], &info);
2093                 if (!W_ERROR_IS_OK(status)) {
2094                         DEBUG(5, ("skipping del of driver with version %d\n",
2095                                   drv_cversion[i]));
2096                         continue;
2097                 }
2098                 found = true;
2099
2100                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2101                         status = WERR_PRINTER_DRIVER_IN_USE;
2102                         goto done;
2103                 }
2104
2105                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2106                 if (!W_ERROR_IS_OK(status)) {
2107                         DEBUG(0, ("failed del of driver with version %d\n",
2108                                   drv_cversion[i]));
2109                         goto done;
2110                 }
2111         }
2112         if (found == false) {
2113                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2114                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2115         } else {
2116                 status = WERR_OK;
2117         }
2118
2119 done:
2120         talloc_free(tmp_ctx);
2121
2122         return status;
2123 }
2124
2125 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2126                                   struct pipes_struct *p,
2127                                   struct spoolss_DeletePrinterDriverEx *r,
2128                                   struct dcerpc_binding_handle *b,
2129                                   struct spoolss_DriverInfo8 *info)
2130 {
2131         WERROR status;
2132         bool delete_files;
2133
2134         if (printer_driver_in_use(mem_ctx, b, info)) {
2135                 status = WERR_PRINTER_DRIVER_IN_USE;
2136                 goto done;
2137         }
2138
2139         /*
2140          * we have a couple of cases to consider.
2141          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2142          *     then the delete should fail if **any** files overlap with
2143          *     other drivers
2144          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2145          *     non-overlapping files
2146          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2147          *     are set, then do not delete any files
2148          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2149          */
2150
2151         delete_files = r->in.delete_flags
2152                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2153
2154
2155         if (delete_files) {
2156                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2157                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2158                         status = WERR_PRINTER_DRIVER_IN_USE;
2159                         goto done;
2160                 }
2161                 /*
2162                  * printer_driver_files_in_use() has trimmed overlapping files
2163                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2164                  */
2165         }
2166
2167
2168         status = winreg_del_driver(mem_ctx, b, info, info->version);
2169         if (!W_ERROR_IS_OK(status)) {
2170                 goto done;
2171         }
2172
2173         /*
2174          * now delete any associated files if delete_files is
2175          * true. Even if this part failes, we return succes
2176          * because the driver doesn not exist any more
2177          */
2178         if (delete_files) {
2179                 delete_driver_files(p->session_info, info);
2180         }
2181
2182 done:
2183         return status;
2184 }
2185
2186 /****************************************************************
2187  _spoolss_DeletePrinterDriverEx
2188 ****************************************************************/
2189
2190 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2191                                       struct spoolss_DeletePrinterDriverEx *r)
2192 {
2193         struct spoolss_DriverInfo8 *info = NULL;
2194         WERROR                          status;
2195         struct dcerpc_binding_handle *b;
2196         TALLOC_CTX *tmp_ctx = NULL;
2197         int i;
2198         bool found;
2199
2200         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2201            and not a printer admin, then fail */
2202
2203         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2204             !security_token_has_privilege(p->session_info->security_token,
2205                                           SEC_PRIV_PRINT_OPERATOR)) {
2206                 return WERR_ACCESS_DENIED;
2207         }
2208
2209         /* check that we have a valid driver name first */
2210         if (get_version_id(r->in.architecture) == -1) {
2211                 /* this is what NT returns */
2212                 return WERR_INVALID_ENVIRONMENT;
2213         }
2214
2215         tmp_ctx = talloc_new(p->mem_ctx);
2216         if (!tmp_ctx) {
2217                 return WERR_NOMEM;
2218         }
2219
2220         status = winreg_printer_binding_handle(tmp_ctx,
2221                                                get_session_info_system(),
2222                                                p->msg_ctx,
2223                                                &b);
2224         if (!W_ERROR_IS_OK(status)) {
2225                 goto done;
2226         }
2227
2228         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2229                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2230                  && (drv_cversion[i] != r->in.version)) {
2231                         continue;
2232                 }
2233
2234                 /* check if a driver with this version exists before delete */
2235                 status = winreg_get_driver(tmp_ctx, b,
2236                                            r->in.architecture, r->in.driver,
2237                                            drv_cversion[i], &info);
2238                 if (!W_ERROR_IS_OK(status)) {
2239                         DEBUG(5, ("skipping del of driver with version %d\n",
2240                                   drv_cversion[i]));
2241                         continue;
2242                 }
2243                 found = true;
2244
2245                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2246                 if (!W_ERROR_IS_OK(status)) {
2247                         DEBUG(0, ("failed to delete driver with version %d\n",
2248                                   drv_cversion[i]));
2249                         goto done;
2250                 }
2251         }
2252         if (found == false) {
2253                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2254                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2255         } else {
2256                 status = WERR_OK;
2257         }
2258
2259 done:
2260         talloc_free(tmp_ctx);
2261         return status;
2262 }
2263
2264
2265 /********************************************************************
2266  GetPrinterData on a printer server Handle.
2267 ********************************************************************/
2268
2269 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2270                                             const char *value,
2271                                             enum winreg_Type *type,
2272                                             union spoolss_PrinterData *data)
2273 {
2274         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2275
2276         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2277                 *type = REG_DWORD;
2278                 SIVAL(&data->value, 0, 0x00);
2279                 return WERR_OK;
2280         }
2281
2282         if (!strcasecmp_m(value, "BeepEnabled")) {
2283                 *type = REG_DWORD;
2284                 SIVAL(&data->value, 0, 0x00);
2285                 return WERR_OK;
2286         }
2287
2288         if (!strcasecmp_m(value, "EventLog")) {
2289                 *type = REG_DWORD;
2290                 /* formally was 0x1b */
2291                 SIVAL(&data->value, 0, 0x00);
2292                 return WERR_OK;
2293         }
2294
2295         if (!strcasecmp_m(value, "NetPopup")) {
2296                 *type = REG_DWORD;
2297                 SIVAL(&data->value, 0, 0x00);
2298                 return WERR_OK;
2299         }
2300
2301         if (!strcasecmp_m(value, "MajorVersion")) {
2302                 *type = REG_DWORD;
2303
2304                 /* Windows NT 4.0 seems to not allow uploading of drivers
2305                    to a server that reports 0x3 as the MajorVersion.
2306                    need to investigate more how Win2k gets around this .
2307                    -- jerry */
2308
2309                 if (RA_WINNT == get_remote_arch()) {
2310                         SIVAL(&data->value, 0, 0x02);
2311                 } else {
2312                         SIVAL(&data->value, 0, 0x03);
2313                 }
2314
2315                 return WERR_OK;
2316         }
2317
2318         if (!strcasecmp_m(value, "MinorVersion")) {
2319                 *type = REG_DWORD;
2320                 SIVAL(&data->value, 0, 0x00);
2321                 return WERR_OK;
2322         }
2323
2324         /* REG_BINARY
2325          *  uint32_t size        = 0x114
2326          *  uint32_t major       = 5
2327          *  uint32_t minor       = [0|1]
2328          *  uint32_t build       = [2195|2600]
2329          *  extra unicode string = e.g. "Service Pack 3"
2330          */
2331         if (!strcasecmp_m(value, "OSVersion")) {
2332                 DATA_BLOB blob;
2333                 enum ndr_err_code ndr_err;
2334                 struct spoolss_OSVersion os;
2335
2336                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
2337                                                       "spoolss", "os_major", 5);
2338                                                       /* Windows 2000 == 5.0 */
2339                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
2340                                                       "spoolss", "os_minor", 0);
2341                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
2342                                                       "spoolss", "os_build", 2195);
2343                 os.extra_string         = "";   /* leave extra string empty */
2344
2345                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2346                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2347                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2348                         return WERR_GENERAL_FAILURE;
2349                 }
2350
2351                 if (DEBUGLEVEL >= 10) {
2352                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2353                 }
2354
2355                 *type = REG_BINARY;
2356                 data->binary = blob;
2357
2358                 return WERR_OK;
2359         }
2360
2361
2362         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2363                 *type = REG_SZ;
2364
2365                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2366                 W_ERROR_HAVE_NO_MEMORY(data->string);
2367
2368                 return WERR_OK;
2369         }
2370
2371         if (!strcasecmp_m(value, "Architecture")) {
2372                 *type = REG_SZ;
2373                 data->string = talloc_strdup(mem_ctx,
2374                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2375                 W_ERROR_HAVE_NO_MEMORY(data->string);
2376
2377                 return WERR_OK;
2378         }
2379
2380         if (!strcasecmp_m(value, "DsPresent")) {
2381                 *type = REG_DWORD;
2382
2383                 /* only show the publish check box if we are a
2384                    member of a AD domain */
2385
2386                 if (lp_security() == SEC_ADS) {
2387                         SIVAL(&data->value, 0, 0x01);
2388                 } else {
2389                         SIVAL(&data->value, 0, 0x00);
2390                 }
2391                 return WERR_OK;
2392         }
2393
2394         if (!strcasecmp_m(value, "DNSMachineName")) {
2395                 const char *hostname = get_mydnsfullname();
2396
2397                 if (!hostname) {
2398                         return WERR_BADFILE;
2399                 }
2400
2401                 *type = REG_SZ;
2402                 data->string = talloc_strdup(mem_ctx, hostname);
2403                 W_ERROR_HAVE_NO_MEMORY(data->string);
2404
2405                 return WERR_OK;
2406         }
2407
2408         *type = REG_NONE;
2409
2410         return WERR_INVALID_PARAM;
2411 }
2412
2413 /****************************************************************
2414  _spoolss_GetPrinterData
2415 ****************************************************************/
2416
2417 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2418                                struct spoolss_GetPrinterData *r)
2419 {
2420         struct spoolss_GetPrinterDataEx r2;
2421
2422         r2.in.handle            = r->in.handle;
2423         r2.in.key_name          = "PrinterDriverData";
2424         r2.in.value_name        = r->in.value_name;
2425         r2.in.offered           = r->in.offered;
2426         r2.out.type             = r->out.type;
2427         r2.out.data             = r->out.data;
2428         r2.out.needed           = r->out.needed;
2429
2430         return _spoolss_GetPrinterDataEx(p, &r2);
2431 }
2432
2433 /*********************************************************
2434  Connect to the client machine.
2435 **********************************************************/
2436
2437 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2438                                       struct sockaddr_storage *client_ss, const char *remote_machine)
2439 {
2440         NTSTATUS ret;
2441         struct sockaddr_storage rm_addr;
2442         char addr[INET6_ADDRSTRLEN];
2443
2444         if ( is_zero_addr(client_ss) ) {
2445                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2446                         remote_machine));
2447                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2448                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2449                         return false;
2450                 }
2451                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2452         } else {
2453                 rm_addr = *client_ss;
2454                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2455                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2456                         addr));
2457         }
2458
2459         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2460                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2461                         addr));
2462                 return false;
2463         }
2464
2465         /* setup the connection */
2466         ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2467                 &rm_addr, 0, "IPC$", "IPC",
2468                 "", /* username */
2469                 "", /* domain */
2470                 "", /* password */
2471                 0, lp_client_signing());
2472
2473         if ( !NT_STATUS_IS_OK( ret ) ) {
2474                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2475                         remote_machine ));
2476                 return false;
2477         }
2478
2479         if ( smbXcli_conn_protocol((*pp_cli)->conn) != PROTOCOL_NT1 ) {
2480                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2481                 cli_shutdown(*pp_cli);
2482                 return false;
2483         }
2484
2485         /*
2486          * Ok - we have an anonymous connection to the IPC$ share.
2487          * Now start the NT Domain stuff :-).
2488          */
2489
2490         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2491         if (!NT_STATUS_IS_OK(ret)) {
2492                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2493                         remote_machine, nt_errstr(ret)));
2494                 cli_shutdown(*pp_cli);
2495                 return false;
2496         }
2497
2498         return true;
2499 }
2500
2501 /***************************************************************************
2502  Connect to the client.
2503 ****************************************************************************/
2504
2505 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2506                                         uint32_t localprinter,
2507                                         enum winreg_Type type,
2508                                         struct policy_handle *handle,
2509                                         struct notify_back_channel **_chan,
2510                                         struct sockaddr_storage *client_ss,
2511                                         struct messaging_context *msg_ctx)
2512 {
2513         WERROR result;
2514         NTSTATUS status;
2515         struct notify_back_channel *chan;
2516
2517         for (chan = back_channels; chan; chan = chan->next) {
2518                 if (memcmp(&chan->client_address, client_ss,
2519                            sizeof(struct sockaddr_storage)) == 0) {
2520                         break;
2521                 }
2522         }
2523
2524         /*
2525          * If it's the first connection, contact the client
2526          * and connect to the IPC$ share anonymously
2527          */
2528         if (!chan) {
2529                 fstring unix_printer;
2530
2531                 /* the +2 is to strip the leading 2 backslashs */
2532                 fstrcpy(unix_printer, printer + 2);
2533
2534                 chan = talloc_zero(NULL, struct notify_back_channel);
2535                 if (!chan) {
2536                         return false;
2537                 }
2538                 chan->client_address = *client_ss;
2539
2540                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2541                         TALLOC_FREE(chan);
2542                         return false;
2543                 }
2544
2545                 DLIST_ADD(back_channels, chan);
2546
2547                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2548                                    receive_notify2_message_list);
2549         }
2550
2551         if (chan->cli_pipe == NULL ||
2552             chan->cli_pipe->binding_handle == NULL) {
2553                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2554                         "NULL %s for printer %s\n",
2555                         chan->cli_pipe == NULL ?
2556                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2557                         printer));
2558                 return false;
2559         }
2560
2561         /*
2562          * Tell the specific printing tdb we want messages for this printer
2563          * by registering our PID.
2564          */
2565
2566         if (!print_notify_register_pid(snum)) {
2567                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2568                           printer));
2569         }
2570
2571         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2572                                                  talloc_tos(),
2573                                                  printer,
2574                                                  localprinter,
2575                                                  type,
2576                                                  0,
2577                                                  NULL,
2578                                                  handle,
2579                                                  &result);
2580         if (!NT_STATUS_IS_OK(status)) {
2581                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2582                 result = ntstatus_to_werror(status);
2583         } else if (!W_ERROR_IS_OK(result)) {
2584                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2585         }
2586
2587         chan->active_connections++;
2588         *_chan = chan;
2589
2590         return (W_ERROR_IS_OK(result));
2591 }
2592
2593 /****************************************************************
2594  ****************************************************************/
2595
2596 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2597                                                              const struct spoolss_NotifyOption *r)
2598 {
2599         struct spoolss_NotifyOption *option;
2600         uint32_t i,k;
2601
2602         if (!r) {
2603                 return NULL;
2604         }
2605
2606         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2607         if (!option) {
2608                 return NULL;
2609         }
2610
2611         *option = *r;
2612
2613         if (!option->count) {
2614                 return option;
2615         }
2616
2617         option->types = talloc_zero_array(option,
2618                 struct spoolss_NotifyOptionType, option->count);
2619         if (!option->types) {
2620                 talloc_free(option);
2621                 return NULL;
2622         }
2623
2624         for (i=0; i < option->count; i++) {
2625                 option->types[i] = r->types[i];
2626
2627                 if (option->types[i].count) {
2628                         option->types[i].fields = talloc_zero_array(option,
2629                                 union spoolss_Field, option->types[i].count);
2630                         if (!option->types[i].fields) {
2631                                 talloc_free(option);
2632                                 return NULL;
2633                         }
2634                         for (k=0; k<option->types[i].count; k++) {
2635                                 option->types[i].fields[k] =
2636                                         r->types[i].fields[k];
2637                         }
2638                 }
2639         }
2640
2641         return option;
2642 }
2643
2644 /****************************************************************
2645  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2646  *
2647  * before replying OK: status=0 a rpc call is made to the workstation
2648  * asking ReplyOpenPrinter
2649  *
2650  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2651  * called from api_spoolss_rffpcnex
2652 ****************************************************************/
2653
2654 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2655                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2656 {
2657         int snum = -1;
2658         struct spoolss_NotifyOption *option = r->in.notify_options;
2659         struct sockaddr_storage client_ss;
2660         ssize_t client_len;
2661
2662         /* store the notify value in the printer struct */
2663
2664         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2665
2666         if (!Printer) {
2667                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2668                         "Invalid handle (%s:%u:%u).\n",
2669                         OUR_HANDLE(r->in.handle)));
2670                 return WERR_BADFID;
2671         }
2672
2673         Printer->notify.flags           = r->in.flags;
2674         Printer->notify.options         = r->in.options;
2675         Printer->notify.printerlocal    = r->in.printer_local;
2676         Printer->notify.msg_ctx         = p->msg_ctx;
2677
2678         TALLOC_FREE(Printer->notify.option);
2679         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2680
2681         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2682
2683         /* Connect to the client machine and send a ReplyOpenPrinter */
2684
2685         if ( Printer->printer_type == SPLHND_SERVER)
2686                 snum = -1;
2687         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2688                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2689                 return WERR_BADFID;
2690
2691         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2692                   "remote_address is %s\n",
2693                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2694
2695         if (!lp_print_notify_backchannel(snum)) {
2696                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2697                         "backchannel disabled\n"));
2698                 return WERR_SERVER_UNAVAILABLE;
2699         }
2700
2701         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2702                                                   (struct sockaddr *) &client_ss,
2703                                                   sizeof(struct sockaddr_storage));
2704         if (client_len < 0) {
2705                 return WERR_NOMEM;
2706         }
2707
2708         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2709                                         Printer->notify.printerlocal, REG_SZ,
2710                                         &Printer->notify.cli_hnd,
2711                                         &Printer->notify.cli_chan,
2712                                         &client_ss, p->msg_ctx)) {
2713                 return WERR_SERVER_UNAVAILABLE;
2714         }
2715
2716         return WERR_OK;
2717 }
2718
2719 /*******************************************************************
2720  * fill a notify_info_data with the servername
2721  ********************************************************************/
2722
2723 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2724                                        int snum,
2725                                        struct spoolss_Notify *data,
2726                                        print_queue_struct *queue,
2727                                        struct spoolss_PrinterInfo2 *pinfo2,
2728                                        TALLOC_CTX *mem_ctx)
2729 {
2730         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2731 }
2732
2733 /*******************************************************************
2734  * fill a notify_info_data with the printername (not including the servername).
2735  ********************************************************************/
2736
2737 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2738                                         int snum,
2739                                         struct spoolss_Notify *data,
2740                                         print_queue_struct *queue,
2741                                         struct spoolss_PrinterInfo2 *pinfo2,
2742                                         TALLOC_CTX *mem_ctx)
2743 {
2744         /* the notify name should not contain the \\server\ part */
2745         const char *p = strrchr(pinfo2->printername, '\\');
2746
2747         if (!p) {
2748                 p = pinfo2->printername;
2749         } else {
2750                 p++;
2751         }
2752
2753         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2754 }
2755
2756 /*******************************************************************
2757  * fill a notify_info_data with the servicename
2758  ********************************************************************/
2759
2760 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2761                                       int snum,
2762                                       struct spoolss_Notify *data,
2763                                       print_queue_struct *queue,
2764                                       struct spoolss_PrinterInfo2 *pinfo2,
2765                                       TALLOC_CTX *mem_ctx)
2766 {
2767         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2768 }
2769
2770 /*******************************************************************
2771  * fill a notify_info_data with the port name
2772  ********************************************************************/
2773
2774 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2775                                      int snum,
2776                                      struct spoolss_Notify *data,
2777                                      print_queue_struct *queue,
2778                                      struct spoolss_PrinterInfo2 *pinfo2,
2779                                      TALLOC_CTX *mem_ctx)
2780 {
2781         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2782 }
2783
2784 /*******************************************************************
2785  * fill a notify_info_data with the printername
2786  * but it doesn't exist, have to see what to do
2787  ********************************************************************/
2788
2789 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2790                                        int snum,
2791                                        struct spoolss_Notify *data,
2792                                        print_queue_struct *queue,
2793                                        struct spoolss_PrinterInfo2 *pinfo2,
2794                                        TALLOC_CTX *mem_ctx)
2795 {
2796         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2797 }
2798
2799 /*******************************************************************
2800  * fill a notify_info_data with the comment
2801  ********************************************************************/
2802
2803 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2804                                    int snum,
2805                                    struct spoolss_Notify *data,
2806                                    print_queue_struct *queue,
2807                                    struct spoolss_PrinterInfo2 *pinfo2,
2808                                    TALLOC_CTX *mem_ctx)
2809 {
2810         const char *p;
2811
2812         if (*pinfo2->comment == '\0') {
2813                 p = lp_comment(talloc_tos(), snum);
2814         } else {
2815                 p = pinfo2->comment;
2816         }
2817
2818         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2819 }
2820
2821 /*******************************************************************
2822  * fill a notify_info_data with the comment
2823  * location = "Room 1, floor 2, building 3"
2824  ********************************************************************/
2825
2826 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2827                                     int snum,
2828                                     struct spoolss_Notify *data,
2829                                     print_queue_struct *queue,
2830                                     struct spoolss_PrinterInfo2 *pinfo2,
2831                                     TALLOC_CTX *mem_ctx)
2832 {
2833         const char *loc = pinfo2->location;
2834         NTSTATUS status;
2835
2836         status = printer_list_get_printer(mem_ctx,
2837                                           pinfo2->sharename,
2838                                           NULL,
2839                                           &loc,
2840                                           NULL);
2841         if (NT_STATUS_IS_OK(status)) {
2842                 if (loc == NULL) {
2843                         loc = pinfo2->location;
2844                 }
2845         }
2846
2847         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2848 }
2849
2850 /*******************************************************************
2851  * fill a notify_info_data with the device mode
2852  * jfm:xxxx don't to it for know but that's a real problem !!!
2853  ********************************************************************/
2854
2855 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2856                                    int snum,
2857                                    struct spoolss_Notify *data,
2858                                    print_queue_struct *queue,
2859                                    struct spoolss_PrinterInfo2 *pinfo2,
2860                                    TALLOC_CTX *mem_ctx)
2861 {
2862         /* for a dummy implementation we have to zero the fields */
2863         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2864 }
2865
2866 /*******************************************************************
2867  * fill a notify_info_data with the separator file name
2868  ********************************************************************/
2869
2870 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2871                                    int snum,
2872                                    struct spoolss_Notify *data,
2873                                    print_queue_struct *queue,
2874                                    struct spoolss_PrinterInfo2 *pinfo2,
2875                                    TALLOC_CTX *mem_ctx)
2876 {
2877         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2878 }
2879
2880 /*******************************************************************
2881  * fill a notify_info_data with the print processor
2882  * jfm:xxxx return always winprint to indicate we don't do anything to it
2883  ********************************************************************/
2884
2885 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2886                                            int snum,
2887                                            struct spoolss_Notify *data,
2888                                            print_queue_struct *queue,
2889                                            struct spoolss_PrinterInfo2 *pinfo2,
2890                                            TALLOC_CTX *mem_ctx)
2891 {
2892         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2893 }
2894
2895 /*******************************************************************
2896  * fill a notify_info_data with the print processor options
2897  * jfm:xxxx send an empty string
2898  ********************************************************************/
2899
2900 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2901                                       int snum,
2902                                       struct spoolss_Notify *data,
2903                                       print_queue_struct *queue,
2904                                       struct spoolss_PrinterInfo2 *pinfo2,
2905                                       TALLOC_CTX *mem_ctx)
2906 {
2907         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2908 }
2909
2910 /*******************************************************************
2911  * fill a notify_info_data with the data type
2912  * jfm:xxxx always send RAW as data type
2913  ********************************************************************/
2914
2915 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2916                                     int snum,
2917                                     struct spoolss_Notify *data,
2918                                     print_queue_struct *queue,
2919                                     struct spoolss_PrinterInfo2 *pinfo2,
2920                                     TALLOC_CTX *mem_ctx)
2921 {
2922         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2923 }
2924
2925 /*******************************************************************
2926  * fill a notify_info_data with the security descriptor
2927  * jfm:xxxx send an null pointer to say no security desc
2928  * have to implement security before !
2929  ********************************************************************/
2930
2931 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2932                                          int snum,
2933                                          struct spoolss_Notify *data,
2934                                          print_queue_struct *queue,
2935                                          struct spoolss_PrinterInfo2 *pinfo2,
2936                                          TALLOC_CTX *mem_ctx)
2937 {
2938         if (pinfo2->secdesc == NULL) {
2939                 data->data.sd.sd = NULL;
2940         } else {
2941                 data->data.sd.sd = security_descriptor_copy(mem_ctx,
2942                                                             pinfo2->secdesc);
2943         }
2944         data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2945                                                              0);
2946 }
2947
2948 /*******************************************************************
2949  * fill a notify_info_data with the attributes
2950  * jfm:xxxx a samba printer is always shared
2951  ********************************************************************/
2952
2953 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2954                                       int snum,
2955                                       struct spoolss_Notify *data,
2956                                       print_queue_struct *queue,
2957                                       struct spoolss_PrinterInfo2 *pinfo2,
2958                                       TALLOC_CTX *mem_ctx)
2959 {
2960         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2961 }
2962
2963 /*******************************************************************
2964  * fill a notify_info_data with the priority
2965  ********************************************************************/
2966
2967 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2968                                     int snum,
2969                                     struct spoolss_Notify *data,
2970                                     print_queue_struct *queue,
2971                                     struct spoolss_PrinterInfo2 *pinfo2,
2972                                     TALLOC_CTX *mem_ctx)
2973 {
2974         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2975 }
2976
2977 /*******************************************************************
2978  * fill a notify_info_data with the default priority
2979  ********************************************************************/
2980
2981 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2982                                             int snum,
2983                                             struct spoolss_Notify *data,
2984                                             print_queue_struct *queue,
2985                                             struct spoolss_PrinterInfo2 *pinfo2,
2986                                             TALLOC_CTX *mem_ctx)
2987 {
2988         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2989 }
2990
2991 /*******************************************************************
2992  * fill a notify_info_data with the start time
2993  ********************************************************************/
2994
2995 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2996                                       int snum,
2997                                       struct spoolss_Notify *data,
2998                                       print_queue_struct *queue,
2999                                       struct spoolss_PrinterInfo2 *pinfo2,
3000                                       TALLOC_CTX *mem_ctx)
3001 {
3002         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3003 }
3004
3005 /*******************************************************************
3006  * fill a notify_info_data with the until time
3007  ********************************************************************/
3008
3009 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3010                                       int snum,
3011                                       struct spoolss_Notify *data,
3012                                       print_queue_struct *queue,
3013                                       struct spoolss_PrinterInfo2 *pinfo2,
3014                                       TALLOC_CTX *mem_ctx)
3015 {
3016         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3017 }
3018
3019 /*******************************************************************
3020  * fill a notify_info_data with the status
3021  ********************************************************************/
3022
3023 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3024                                   int snum,
3025                                   struct spoolss_Notify *data,
3026                                   print_queue_struct *queue,
3027                                   struct spoolss_PrinterInfo2 *pinfo2,
3028                                   TALLOC_CTX *mem_ctx)
3029 {
3030         print_status_struct status;
3031
3032         print_queue_length(msg_ctx, snum, &status);
3033         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3034 }
3035
3036 /*******************************************************************
3037  * fill a notify_info_data with the number of jobs queued
3038  ********************************************************************/
3039
3040 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3041                                  int snum,
3042                                  struct spoolss_Notify *data,
3043                                  print_queue_struct *queue,
3044                                  struct spoolss_PrinterInfo2 *pinfo2,
3045                                  TALLOC_CTX *mem_ctx)
3046 {
3047         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3048                 data, print_queue_length(msg_ctx, snum, NULL));
3049 }
3050
3051 /*******************************************************************
3052  * fill a notify_info_data with the average ppm
3053  ********************************************************************/
3054
3055 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3056                                        int snum,
3057                                        struct spoolss_Notify *data,
3058                                        print_queue_struct *queue,
3059                                        struct spoolss_PrinterInfo2 *pinfo2,
3060                                        TALLOC_CTX *mem_ctx)
3061 {
3062         /* always respond 8 pages per minutes */
3063         /* a little hard ! */
3064         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3065 }
3066
3067 /*******************************************************************
3068  * fill a notify_info_data with username
3069  ********************************************************************/
3070
3071 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3072                                     int snum,
3073                                     struct spoolss_Notify *data,
3074                                     print_queue_struct *queue,
3075                                     struct spoolss_PrinterInfo2 *pinfo2,
3076                                     TALLOC_CTX *mem_ctx)
3077 {
3078         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3079 }
3080
3081 /*******************************************************************
3082  * fill a notify_info_data with job status
3083  ********************************************************************/
3084
3085 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3086                                       int snum,
3087                                       struct spoolss_Notify *data,
3088                                       print_queue_struct *queue,
3089                                       struct spoolss_PrinterInfo2 *pinfo2,
3090                                       TALLOC_CTX *mem_ctx)
3091 {
3092         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3093 }
3094
3095 /*******************************************************************
3096  * fill a notify_info_data with job name
3097  ********************************************************************/
3098
3099 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3100                                     int snum,
3101                                     struct spoolss_Notify *data,
3102                                     print_queue_struct *queue,
3103                                     struct spoolss_PrinterInfo2 *pinfo2,
3104                                     TALLOC_CTX *mem_ctx)
3105 {
3106         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3107 }
3108
3109 /*******************************************************************
3110  * fill a notify_info_data with job status
3111  ********************************************************************/
3112
3113 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3114                                              int snum,
3115                                              struct spoolss_Notify *data,
3116                                              print_queue_struct *queue,
3117                                              struct spoolss_PrinterInfo2 *pinfo2,
3118                                              TALLOC_CTX *mem_ctx)
3119 {
3120         /*
3121          * Now we're returning job status codes we just return a "" here. JRA.
3122          */
3123
3124         const char *p = "";
3125
3126 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3127         p = "unknown";
3128
3129         switch (queue->status) {
3130         case LPQ_QUEUED:
3131                 p = "Queued";
3132                 break;
3133         case LPQ_PAUSED:
3134                 p = "";    /* NT provides the paused string */
3135                 break;
3136         case LPQ_SPOOLING:
3137                 p = "Spooling";
3138                 break;
3139         case LPQ_PRINTING:
3140                 p = "Printing";
3141                 break;
3142         }
3143 #endif /* NO LONGER NEEDED. */
3144
3145         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3146 }
3147
3148 /*******************************************************************
3149  * fill a notify_info_data with job time
3150  ********************************************************************/
3151
3152 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3153                                     int snum,
3154                                     struct spoolss_Notify *data,
3155                                     print_queue_struct *queue,
3156                                     struct spoolss_PrinterInfo2 *pinfo2,
3157                                     TALLOC_CTX *mem_ctx)
3158 {
3159         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3160 }
3161
3162 /*******************************************************************
3163  * fill a notify_info_data with job size
3164  ********************************************************************/
3165
3166 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3167                                     int snum,
3168                                     struct spoolss_Notify *data,
3169                                     print_queue_struct *queue,
3170                                     struct spoolss_PrinterInfo2 *pinfo2,
3171                                     TALLOC_CTX *mem_ctx)
3172 {
3173         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3174 }
3175
3176 /*******************************************************************
3177  * fill a notify_info_data with page info
3178  ********************************************************************/
3179 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3180                                        int snum,
3181                                 struct spoolss_Notify *data,
3182                                 print_queue_struct *queue,
3183                                 struct spoolss_PrinterInfo2 *pinfo2,
3184                                 TALLOC_CTX *mem_ctx)
3185 {
3186         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3187 }
3188
3189 /*******************************************************************
3190  * fill a notify_info_data with pages printed info.
3191  ********************************************************************/
3192 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3193                                          int snum,
3194                                 struct spoolss_Notify *data,
3195                                 print_queue_struct *queue,
3196                                 struct spoolss_PrinterInfo2 *pinfo2,
3197                                 TALLOC_CTX *mem_ctx)
3198 {
3199         /* Add code when back-end tracks this */
3200         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3201 }
3202
3203 /*******************************************************************
3204  Fill a notify_info_data with job position.
3205  ********************************************************************/
3206
3207 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3208                                         int snum,
3209                                         struct spoolss_Notify *data,
3210                                         print_queue_struct *queue,
3211                                         struct spoolss_PrinterInfo2 *pinfo2,
3212                                         TALLOC_CTX *mem_ctx)
3213 {
3214         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3215 }
3216
3217 /*******************************************************************
3218  Fill a notify_info_data with submitted time.
3219  ********************************************************************/
3220
3221 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3222                                           int snum,
3223                                           struct spoolss_Notify *data,
3224                                           print_queue_struct *queue,
3225                                           struct spoolss_PrinterInfo2 *pinfo2,
3226                                           TALLOC_CTX *mem_ctx)
3227 {
3228         data->data.string.string = NULL;
3229         data->data.string.size = 0;
3230
3231         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3232                                &data->data.string.string,
3233                                &data->data.string.size);
3234
3235 }
3236
3237 struct s_notify_info_data_table
3238 {
3239         enum spoolss_NotifyType type;
3240         uint16_t field;
3241         const char *name;
3242         enum spoolss_NotifyTable variable_type;
3243         void (*fn) (struct messaging_context *msg_ctx,
3244                     int snum, struct spoolss_Notify *data,
3245                     print_queue_struct *queue,
3246                     struct spoolss_PrinterInfo2 *pinfo2,
3247                     TALLOC_CTX *mem_ctx);
3248 };
3249
3250 /* A table describing the various print notification constants and
3251    whether the notification data is a pointer to a variable sized
3252    buffer, a one value uint32_t or a two value uint32_t. */
3253
3254 static const struct s_notify_info_data_table notify_info_data_table[] =
3255 {
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3282 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3283 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3284 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3285 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3286 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3287 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3288 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3289 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3290 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3291 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3305 };
3306
3307 /*******************************************************************
3308  Return the variable_type of info_data structure.
3309 ********************************************************************/
3310
3311 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3312                                                                   uint16_t field)
3313 {
3314         int i=0;
3315
3316         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3317                 if ( (notify_info_data_table[i].type == type) &&
3318                      (notify_info_data_table[i].field == field) ) {
3319                         return notify_info_data_table[i].variable_type;
3320                 }
3321         }
3322
3323         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3324
3325         return (enum spoolss_NotifyTable) 0;
3326 }
3327
3328 /****************************************************************************
3329 ****************************************************************************/
3330
3331 static bool search_notify(enum spoolss_NotifyType type,
3332                           uint16_t field,
3333                           int *value)
3334 {
3335         int i;
3336
3337         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3338                 if (notify_info_data_table[i].type == type &&
3339                     notify_info_data_table[i].field == field &&
3340                     notify_info_data_table[i].fn != NULL) {
3341                         *value = i;
3342                         return true;
3343                 }
3344         }
3345
3346         return false;
3347 }
3348
3349 /****************************************************************************
3350 ****************************************************************************/
3351
3352 static void construct_info_data(struct spoolss_Notify *info_data,
3353                                 enum spoolss_NotifyType type,
3354                                 uint16_t field, int id)
3355 {
3356         info_data->type                 = type;
3357         info_data->field.field          = field;
3358         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3359         info_data->job_id               = id;
3360 }
3361
3362 /*******************************************************************
3363  *
3364  * fill a notify_info struct with info asked
3365  *
3366  ********************************************************************/
3367
3368 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3369                                           struct printer_handle *print_hnd,
3370                                           struct spoolss_NotifyInfo *info,
3371                                           struct spoolss_PrinterInfo2 *pinfo2,
3372                                           int snum,
3373                                           const struct spoolss_NotifyOptionType *option_type,
3374                                           uint32_t id,
3375                                           TALLOC_CTX *mem_ctx)
3376 {
3377         int field_num,j;
3378         enum spoolss_NotifyType type;
3379         uint16_t field;
3380
3381         struct spoolss_Notify *current_data;
3382
3383         type = option_type->type;
3384
3385         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3386                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3387                 option_type->count, lp_servicename(talloc_tos(), snum)));
3388
3389         for(field_num=0; field_num < option_type->count; field_num++) {
3390                 field = option_type->fields[field_num].field;
3391
3392                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3393
3394                 if (!search_notify(type, field, &j) )
3395                         continue;
3396
3397                 info->notifies = talloc_realloc(info, info->notifies,
3398                                                       struct spoolss_Notify,
3399                                                       info->count + 1);
3400                 if (info->notifies == NULL) {
3401                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3402                         return false;
3403                 }
3404
3405                 current_data = &info->notifies[info->count];
3406
3407                 construct_info_data(current_data, type, field, id);
3408
3409                 DEBUG(10, ("construct_notify_printer_info: "
3410                            "calling [%s]  snum=%d  printername=[%s])\n",
3411                            notify_info_data_table[j].name, snum,
3412                            pinfo2->printername));
3413
3414                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3415                                              NULL, pinfo2, mem_ctx);
3416
3417                 info->count++;
3418         }
3419
3420         return true;
3421 }
3422
3423 /*******************************************************************
3424  *
3425  * fill a notify_info struct with info asked
3426  *
3427  ********************************************************************/
3428
3429 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3430                                        print_queue_struct *queue,
3431                                        struct spoolss_NotifyInfo *info,
3432                                        struct spoolss_PrinterInfo2 *pinfo2,
3433                                        int snum,
3434                                        const struct spoolss_NotifyOptionType *option_type,
3435                                        uint32_t id,
3436                                        TALLOC_CTX *mem_ctx)
3437 {
3438         int field_num,j;
3439         enum spoolss_NotifyType type;
3440         uint16_t field;
3441         struct spoolss_Notify *current_data;
3442
3443         DEBUG(4,("construct_notify_jobs_info\n"));
3444
3445         type = option_type->type;
3446
3447         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3448                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3449                 option_type->count));
3450
3451         for(field_num=0; field_num<option_type->count; field_num++) {
3452                 field = option_type->fields[field_num].field;
3453
3454                 if (!search_notify(type, field, &j) )
3455                         continue;
3456
3457                 info->notifies = talloc_realloc(info, info->notifies,
3458                                                       struct spoolss_Notify,
3459                                                       info->count + 1);
3460                 if (info->notifies == NULL) {
3461                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3462                         return false;
3463                 }
3464
3465                 current_data=&(info->notifies[info->count]);
3466
3467                 construct_info_data(current_data, type, field, id);
3468                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3469                                              queue, pinfo2, mem_ctx);
3470                 info->count++;
3471         }
3472
3473         return true;
3474 }
3475
3476 /*
3477  * JFM: The enumeration is not that simple, it's even non obvious.
3478  *
3479  * let's take an example: I want to monitor the PRINTER SERVER for
3480  * the printer's name and the number of jobs currently queued.
3481  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3482  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3483  *
3484  * I have 3 printers on the back of my server.
3485  *
3486  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3487  * structures.
3488  *   Number     Data                    Id
3489  *      1       printer 1 name          1
3490  *      2       printer 1 cjob          1
3491  *      3       printer 2 name          2
3492  *      4       printer 2 cjob          2
3493  *      5       printer 3 name          3
3494  *      6       printer 3 name          3
3495  *
3496  * that's the print server case, the printer case is even worse.
3497  */
3498
3499 /*******************************************************************
3500  *
3501  * enumerate all printers on the printserver
3502  * fill a notify_info struct with info asked
3503  *
3504  ********************************************************************/
3505
3506 static WERROR printserver_notify_info(struct pipes_struct *p,
3507                                       struct policy_handle *hnd,
3508                                       struct spoolss_NotifyInfo *info,
3509                                       TALLOC_CTX *mem_ctx)
3510 {
3511         int snum;
3512         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3513         int n_services=lp_numservices();
3514         int i;
3515         struct spoolss_NotifyOption *option;
3516         struct spoolss_NotifyOptionType option_type;
3517         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3518         WERROR result;
3519
3520         DEBUG(4,("printserver_notify_info\n"));
3521
3522         if (!Printer)
3523                 return WERR_BADFID;
3524
3525         option = Printer->notify.option;
3526
3527         info->version   = 2;
3528         info->notifies  = NULL;
3529         info->count     = 0;
3530
3531         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3532            sending a ffpcn() request first */
3533
3534         if ( !option )
3535                 return WERR_BADFID;
3536
3537         for (i=0; i<option->count; i++) {
3538                 option_type = option->types[i];
3539
3540                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3541                         continue;
3542
3543                 for (snum = 0; snum < n_services; snum++) {
3544                         if (!lp_browseable(snum) ||
3545                             !lp_snum_ok(snum) ||
3546                             !lp_printable(snum)) {
3547                                 continue; /* skip */
3548                         }
3549
3550                         /* Maybe we should use the SYSTEM session_info here... */
3551                         result = winreg_get_printer_internal(mem_ctx,
3552                                                     get_session_info_system(),
3553                                                     p->msg_ctx,
3554                                                     lp_servicename(talloc_tos(), snum),
3555                                                     &pinfo2);
3556                         if (!W_ERROR_IS_OK(result)) {
3557                                 DEBUG(4, ("printserver_notify_info: "
3558                                           "Failed to get printer [%s]\n",
3559                                           lp_servicename(talloc_tos(), snum)));
3560                                 continue;
3561                         }
3562
3563
3564                         construct_notify_printer_info(p->msg_ctx,
3565                                                       Printer, info,
3566                                                       pinfo2, snum,
3567                                                       &option_type, snum,
3568                                                       mem_ctx);
3569
3570                         TALLOC_FREE(pinfo2);
3571                 }
3572         }
3573
3574 #if 0
3575         /*
3576          * Debugging information, don't delete.
3577          */
3578
3579         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3580         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3581         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3582
3583         for (i=0; i<info->count; i++) {
3584                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3585                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3586                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3587         }
3588 #endif
3589
3590         return WERR_OK;
3591 }
3592
3593 /*******************************************************************
3594  *
3595  * fill a notify_info struct with info asked
3596  *
3597  ********************************************************************/
3598
3599 static WERROR printer_notify_info(struct pipes_struct *p,
3600                                   struct policy_handle *hnd,
3601                                   struct spoolss_NotifyInfo *info,
3602                                   TALLOC_CTX *mem_ctx)
3603 {
3604         int snum;
3605         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3606         int i;
3607         uint32_t id;
3608         struct spoolss_NotifyOption *option;
3609         struct spoolss_NotifyOptionType option_type;
3610         int count,j;
3611         print_queue_struct *queue=NULL;
3612         print_status_struct status;
3613         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3614         WERROR result;
3615         struct tdb_print_db *pdb;
3616
3617         DEBUG(4,("printer_notify_info\n"));
3618
3619         if (!Printer)
3620                 return WERR_BADFID;
3621
3622         option = Printer->notify.option;
3623         id = 0x0;
3624
3625         info->version   = 2;
3626         info->notifies  = NULL;
3627         info->count     = 0;
3628
3629         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3630            sending a ffpcn() request first */
3631
3632         if ( !option )
3633                 return WERR_BADFID;
3634
3635         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3636                 return WERR_BADFID;
3637         }
3638
3639         pdb = get_print_db_byname(Printer->sharename);
3640         if (pdb == NULL) {
3641                 return WERR_BADFID;
3642         }
3643
3644         /* Maybe we should use the SYSTEM session_info here... */
3645         result = winreg_get_printer_internal(mem_ctx,
3646                                     get_session_info_system(),
3647                                     p->msg_ctx,
3648                                     lp_servicename(talloc_tos(), snum), &pinfo2);
3649         if (!W_ERROR_IS_OK(result)) {
3650                 result = WERR_BADFID;
3651                 goto err_pdb_drop;
3652         }
3653
3654         /*
3655          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3656          * correct servername.
3657          */
3658         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3659         if (pinfo2->servername == NULL) {
3660                 result = WERR_NOMEM;
3661                 goto err_pdb_drop;
3662         }
3663
3664         for (i = 0; i < option->count; i++) {
3665                 option_type = option->types[i];
3666
3667                 switch (option_type.type) {
3668                 case PRINTER_NOTIFY_TYPE:
3669                         if (construct_notify_printer_info(p->msg_ctx,
3670                                                           Printer, info,
3671                                                           pinfo2, snum,
3672                                                           &option_type, id,
3673                                                           mem_ctx)) {
3674                                 id--;
3675                         }
3676                         break;
3677
3678                 case JOB_NOTIFY_TYPE:
3679
3680                         count = print_queue_status(p->msg_ctx, snum, &queue,
3681                                                    &status);
3682
3683                         for (j = 0; j < count; j++) {
3684                                 uint32_t jobid;
3685                                 jobid = sysjob_to_jobid_pdb(pdb,
3686                                                             queue[j].sysjob);
3687                                 if (jobid == (uint32_t)-1) {
3688                                         DEBUG(2, ("ignoring untracked job %d\n",
3689                                                   queue[j].sysjob));
3690                                         continue;
3691                                 }
3692                                 /* FIXME check return value */
3693                                 construct_notify_jobs_info(p->msg_ctx,
3694                                                            &queue[j], info,
3695                                                            pinfo2, snum,
3696                                                            &option_type,
3697                                                            jobid,
3698                                                            mem_ctx);
3699                         }
3700
3701                         SAFE_FREE(queue);
3702                         break;
3703                 }
3704         }
3705
3706         /*
3707          * Debugging information, don't delete.
3708          */
3709         /*
3710         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3711         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3712         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3713
3714         for (i=0; i<info->count; i++) {
3715                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3716                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3717                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3718         }
3719         */
3720
3721         talloc_free(pinfo2);
3722         result = WERR_OK;
3723 err_pdb_drop:
3724         release_print_db(pdb);
3725         return result;
3726 }
3727
3728 /****************************************************************
3729  _spoolss_RouterRefreshPrinterChangeNotify
3730 ****************************************************************/
3731
3732 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3733                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3734 {
3735         struct spoolss_NotifyInfo *info;
3736
3737         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3738         WERROR result = WERR_BADFID;
3739
3740         /* we always have a spoolss_NotifyInfo struct */
3741         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3742         if (!info) {
3743                 result = WERR_NOMEM;
3744                 goto done;
3745         }
3746
3747         *r->out.info = info;
3748
3749         if (!Printer) {
3750                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3751                         "Invalid handle (%s:%u:%u).\n",
3752                         OUR_HANDLE(r->in.handle)));
3753                 goto done;
3754         }
3755
3756         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3757
3758         /*
3759          *      We are now using the change value, and
3760          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3761          *      I don't have a global notification system, I'm sending back all the
3762          *      information even when _NOTHING_ has changed.
3763          */
3764
3765         /* We need to keep track of the change value to send back in
3766            RRPCN replies otherwise our updates are ignored. */
3767
3768         Printer->notify.fnpcn = true;
3769
3770         if (Printer->notify.cli_chan != NULL &&
3771             Printer->notify.cli_chan->active_connections > 0) {
3772                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3773                         "Saving change value in request [%x]\n",
3774                         r->in.change_low));
3775                 Printer->notify.change = r->in.change_low;
3776         }
3777
3778         /* just ignore the spoolss_NotifyOption */
3779
3780         switch (Printer->printer_type) {
3781                 case SPLHND_SERVER:
3782                         result = printserver_notify_info(p, r->in.handle,
3783                                                          info, p->mem_ctx);
3784                         break;
3785
3786                 case SPLHND_PRINTER:
3787                         result = printer_notify_info(p, r->in.handle,
3788                                                      info, p->mem_ctx);
3789                         break;
3790         }
3791
3792         Printer->notify.fnpcn = false;
3793
3794 done:
3795         return result;
3796 }
3797
3798 /********************************************************************
3799  ********************************************************************/
3800
3801 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3802                                  const char *servername,
3803                                  const char *printername,
3804                                  const char **printername_p)
3805 {
3806         /* FIXME: add lp_force_printername() */
3807
3808         if (servername == NULL) {
3809                 *printername_p = talloc_strdup(mem_ctx, printername);
3810                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3811                 return WERR_OK;
3812         }
3813
3814         if (servername[0] == '\\' && servername[1] == '\\') {
3815                 servername += 2;
3816         }
3817
3818         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3819         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3820
3821         return WERR_OK;
3822 }
3823
3824 /********************************************************************
3825  ********************************************************************/
3826
3827 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3828                                           const char *printername)
3829 {
3830         if (dm == NULL) {
3831                 return;
3832         }
3833
3834         dm->devicename = talloc_strndup(dm, printername,
3835                                         MIN(strlen(printername), 31));
3836 }
3837
3838 /********************************************************************
3839  * construct_printer_info_0
3840  * fill a printer_info_0 struct
3841  ********************************************************************/
3842
3843 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3844                                       const struct auth_session_info *session_info,
3845                                       struct messaging_context *msg_ctx,
3846                                       struct spoolss_PrinterInfo2 *info2,
3847                                       const char *servername,
3848                                       struct spoolss_PrinterInfo0 *r,
3849                                       int snum)
3850 {
3851         int count;
3852         struct printer_session_counter *session_counter;
3853         struct timeval setuptime;
3854         print_status_struct status;
3855         WERROR result;
3856
3857         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3858         if (!W_ERROR_IS_OK(result)) {
3859                 return result;
3860         }
3861
3862         if (servername) {
3863                 r->servername = talloc_strdup(mem_ctx, servername);
3864                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3865         } else {
3866                 r->servername = NULL;
3867         }
3868
3869         count = print_queue_length(msg_ctx, snum, &status);
3870
3871         /* check if we already have a counter for this printer */
3872         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3873                 if (session_counter->snum == snum)
3874                         break;
3875         }
3876
3877         /* it's the first time, add it to the list */
3878         if (session_counter == NULL) {
3879                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3880                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3881                 session_counter->snum           = snum;
3882                 session_counter->counter        = 0;
3883                 DLIST_ADD(counter_list, session_counter);
3884         }
3885
3886         /* increment it */
3887         session_counter->counter++;
3888
3889         r->cjobs                        = count;
3890         r->total_jobs                   = 0;
3891         r->total_bytes                  = 0;
3892
3893         get_startup_time(&setuptime);
3894         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3895
3896         /* JFM:
3897          * the global_counter should be stored in a TDB as it's common to all the clients
3898          * and should be zeroed on samba startup
3899          */
3900         r->global_counter               = session_counter->counter;
3901         r->total_pages                  = 0;
3902         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3903         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3904         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3905         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3906         r->spooling                     = 0;
3907         r->max_spooling                 = 0;
3908         r->session_counter              = session_counter->counter;
3909         r->num_error_out_of_paper       = 0x0;
3910         r->num_error_not_ready          = 0x0;          /* number of print failure */
3911         r->job_error                    = 0x0;
3912         r->number_of_processors         = 0x1;
3913         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3914         r->high_part_total_bytes        = 0x0;
3915
3916         /* ChangeID in milliseconds*/
3917         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3918                                     info2->sharename, &r->change_id);
3919
3920         r->last_error                   = WERR_OK;
3921         r->status                       = nt_printq_status(status.status);
3922         r->enumerate_network_printers   = 0x0;
3923         r->c_setprinter                 = 0x0;
3924         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3925         r->processor_level              = 0x6;          /* 6  ???*/
3926         r->ref_ic                       = 0;
3927         r->reserved2                    = 0;
3928         r->reserved3                    = 0;
3929
3930         return WERR_OK;
3931 }
3932
3933
3934 /********************************************************************
3935  * construct_printer_info1
3936  * fill a spoolss_PrinterInfo1 struct
3937 ********************************************************************/
3938
3939 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3940                                       const struct spoolss_PrinterInfo2 *info2,
3941                                       uint32_t flags,
3942                                       const char *servername,
3943                                       struct spoolss_PrinterInfo1 *r,
3944                                       int snum)
3945 {
3946         WERROR result;
3947
3948         r->flags                = flags;
3949
3950         if (info2->comment == NULL || info2->comment[0] == '\0') {
3951                 r->comment      = lp_comment(mem_ctx, snum);
3952         } else {
3953                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3954         }
3955         W_ERROR_HAVE_NO_MEMORY(r->comment);
3956
3957         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3958         if (!W_ERROR_IS_OK(result)) {
3959                 return result;
3960         }
3961
3962         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3963                                                   r->name,
3964                                                   info2->drivername,
3965                                                   r->comment);
3966         W_ERROR_HAVE_NO_MEMORY(r->description);
3967
3968         return WERR_OK;
3969 }
3970
3971 /********************************************************************
3972  * construct_printer_info2
3973  * fill a spoolss_PrinterInfo2 struct
3974 ********************************************************************/
3975
3976 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3977                                       struct messaging_context *msg_ctx,
3978                                       const struct spoolss_PrinterInfo2 *info2,
3979                                       const char *servername,
3980                                       struct spoolss_PrinterInfo2 *r,
3981                                       int snum)
3982 {
3983         int count;
3984         print_status_struct status;
3985         WERROR result;
3986
3987         count = print_queue_length(msg_ctx, snum, &status);
3988
3989         if (servername) {
3990                 r->servername           = talloc_strdup(mem_ctx, servername);
3991                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3992         } else {
3993                 r->servername           = NULL;
3994         }
3995
3996         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3997         if (!W_ERROR_IS_OK(result)) {
3998                 return result;
3999         }
4000
4001         r->sharename            = lp_servicename(mem_ctx, snum);
4002         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4003         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4004         W_ERROR_HAVE_NO_MEMORY(r->portname);
4005         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4006         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4007
4008         if (info2->comment[0] == '\0') {
4009                 r->comment      = lp_comment(mem_ctx, snum);
4010         } else {
4011                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4012         }
4013         W_ERROR_HAVE_NO_MEMORY(r->comment);
4014
4015         r->location     = talloc_strdup(mem_ctx, info2->location);
4016         if (info2->location[0] == '\0') {
4017                 const char *loc = NULL;
4018                 NTSTATUS nt_status;
4019
4020                 nt_status = printer_list_get_printer(mem_ctx,
4021                                                      info2->sharename,
4022                                                      NULL,
4023                                                      &loc,
4024                                                      NULL);
4025                 if (NT_STATUS_IS_OK(nt_status)) {
4026                         if (loc != NULL) {
4027                                 r->location = talloc_strdup(mem_ctx, loc);
4028                         }
4029                 }
4030         }
4031         W_ERROR_HAVE_NO_MEMORY(r->location);
4032
4033         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4034         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4035         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4036         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4037         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4038         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4039         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4040         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4041
4042         r->attributes           = info2->attributes;
4043
4044         r->priority             = info2->priority;
4045         r->defaultpriority      = info2->defaultpriority;
4046         r->starttime            = info2->starttime;
4047         r->untiltime            = info2->untiltime;
4048         r->status               = nt_printq_status(status.status);
4049         r->cjobs                = count;
4050         r->averageppm           = info2->averageppm;
4051
4052         if (info2->devmode != NULL) {
4053                 result = copy_devicemode(mem_ctx,
4054                                          info2->devmode,
4055                                          &r->devmode);
4056                 if (!W_ERROR_IS_OK(result)) {
4057                         return result;
4058                 }
4059         } else if (lp_default_devmode(snum)) {
4060                 result = spoolss_create_default_devmode(mem_ctx,
4061                                                         info2->printername,
4062                                                         &r->devmode);
4063                 if (!W_ERROR_IS_OK(result)) {
4064                         return result;
4065                 }
4066         } else {
4067                 r->devmode = NULL;
4068                 DEBUG(8,("Returning NULL Devicemode!\n"));
4069         }
4070
4071         compose_devicemode_devicename(r->devmode, r->printername);
4072
4073         r->secdesc = NULL;
4074
4075         if (info2->secdesc != NULL) {
4076                 /* don't use talloc_steal() here unless you do a deep steal of all
4077                    the SEC_DESC members */
4078
4079                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4080                 if (r->secdesc == NULL) {
4081                         return WERR_NOMEM;
4082                 }
4083         }
4084
4085         return WERR_OK;
4086 }
4087
4088 /********************************************************************
4089  * construct_printer_info3
4090  * fill a spoolss_PrinterInfo3 struct
4091  ********************************************************************/
4092
4093 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4094                                       const struct spoolss_PrinterInfo2 *info2,
4095                                       const char *servername,
4096                                       struct spoolss_PrinterInfo3 *r,
4097                                       int snum)
4098 {
4099         /* These are the components of the SD we are returning. */
4100
4101         if (info2->secdesc != NULL) {
4102                 /* don't use talloc_steal() here unless you do a deep steal of all
4103                    the SEC_DESC members */
4104
4105                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4106                 if (r->secdesc == NULL) {
4107                         return WERR_NOMEM;
4108                 }
4109         }
4110
4111         return WERR_OK;
4112 }
4113
4114 /********************************************************************
4115  * construct_printer_info4
4116  * fill a spoolss_PrinterInfo4 struct
4117  ********************************************************************/
4118
4119 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4120                                       const struct spoolss_PrinterInfo2 *info2,
4121                                       const char *servername,
4122                                       struct spoolss_PrinterInfo4 *r,
4123                                       int snum)
4124 {
4125         WERROR result;
4126
4127         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4128         if (!W_ERROR_IS_OK(result)) {
4129                 return result;
4130         }
4131
4132         if (servername) {
4133                 r->servername   = talloc_strdup(mem_ctx, servername);
4134                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4135         } else {
4136                 r->servername = NULL;
4137         }
4138
4139         r->attributes   = info2->attributes;
4140
4141         return WERR_OK;
4142 }
4143
4144 /********************************************************************
4145  * construct_printer_info5
4146  * fill a spoolss_PrinterInfo5 struct
4147  ********************************************************************/
4148
4149 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4150                                       const struct spoolss_PrinterInfo2 *info2,
4151                                       const char *servername,
4152                                       struct spoolss_PrinterInfo5 *r,
4153                                       int snum)
4154 {
4155         WERROR result;
4156
4157         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4158         if (!W_ERROR_IS_OK(result)) {
4159                 return result;
4160         }
4161
4162         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4163         W_ERROR_HAVE_NO_MEMORY(r->portname);
4164
4165         r->attributes   = info2->attributes;
4166
4167         /* these two are not used by NT+ according to MSDN */
4168         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4169         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4170
4171         return WERR_OK;
4172 }
4173
4174 /********************************************************************
4175  * construct_printer_info_6
4176  * fill a spoolss_PrinterInfo6 struct
4177  ********************************************************************/
4178
4179 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4180                                       struct messaging_context *msg_ctx,
4181                                       const struct spoolss_PrinterInfo2 *info2,
4182                                       const char *servername,
4183                                       struct spoolss_PrinterInfo6 *r,
4184                                       int snum)
4185 {
4186         print_status_struct status;
4187
4188         print_queue_length(msg_ctx, snum, &status);
4189
4190         r->status = nt_printq_status(status.status);
4191
4192         return WERR_OK;
4193 }
4194
4195 /********************************************************************
4196  * construct_printer_info7
4197  * fill a spoolss_PrinterInfo7 struct
4198  ********************************************************************/
4199
4200 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4201                                       struct messaging_context *msg_ctx,
4202                                       const char *servername,
4203                                       struct spoolss_PrinterInfo7 *r,
4204                                       int snum)
4205 {
4206         const struct auth_session_info *session_info;
4207         char *printer;
4208         WERROR werr;
4209         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4210         if (tmp_ctx == NULL) {
4211                 return WERR_NOMEM;
4212         }
4213
4214         session_info = get_session_info_system();
4215         SMB_ASSERT(session_info != NULL);
4216
4217         printer = lp_servicename(tmp_ctx, snum);
4218         if (printer == NULL) {
4219                 DEBUG(0, ("invalid printer snum %d\n", snum));
4220                 werr = WERR_INVALID_PARAM;
4221                 goto out_tmp_free;
4222         }
4223
4224         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4225                                  servername, printer, NULL)) {
4226                 struct GUID guid;
4227                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4228                                            printer, &guid);
4229                 if (!W_ERROR_IS_OK(werr)) {
4230                         goto out_tmp_free;
4231                 }
4232                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4233                 r->action = DSPRINT_PUBLISH;
4234         } else {
4235                 r->guid = talloc_strdup(mem_ctx, "");
4236                 r->action = DSPRINT_UNPUBLISH;
4237         }
4238         if (r->guid == NULL) {
4239                 werr = WERR_NOMEM;
4240                 goto out_tmp_free;
4241         }
4242
4243         werr = WERR_OK;
4244 out_tmp_free:
4245         talloc_free(tmp_ctx);
4246         return werr;
4247 }
4248
4249 /********************************************************************
4250  * construct_printer_info8
4251  * fill a spoolss_PrinterInfo8 struct
4252  ********************************************************************/
4253
4254 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4255                                       const struct spoolss_PrinterInfo2 *info2,
4256                                       const char *servername,
4257                                       struct spoolss_DeviceModeInfo *r,
4258                                       int snum)
4259 {
4260         WERROR result;
4261         const char *printername;
4262
4263         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4264         if (!W_ERROR_IS_OK(result)) {
4265                 return result;
4266         }
4267
4268         if (info2->devmode != NULL) {
4269                 result = copy_devicemode(mem_ctx,
4270                                          info2->devmode,
4271                                          &r->devmode);
4272                 if (!W_ERROR_IS_OK(result)) {
4273                         return result;
4274                 }
4275         } else if (lp_default_devmode(snum)) {
4276                 result = spoolss_create_default_devmode(mem_ctx,
4277                                                         info2->printername,
4278                                                         &r->devmode);
4279                 if (!W_ERROR_IS_OK(result)) {
4280                         return result;
4281                 }
4282         } else {
4283                 r->devmode = NULL;
4284                 DEBUG(8,("Returning NULL Devicemode!\n"));
4285         }
4286
4287         compose_devicemode_devicename(r->devmode, printername);
4288
4289         return WERR_OK;
4290 }
4291
4292 /********************************************************************
4293  Spoolss_enumprinters.
4294 ********************************************************************/
4295
4296 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4297                                            const struct auth_session_info *session_info,
4298                                            struct messaging_context *msg_ctx,
4299                                            const char *servername,
4300                                            uint32_t level,
4301                                            uint32_t flags,
4302                                            union spoolss_PrinterInfo **info_p,
4303                                            uint32_t *count_p)
4304 {
4305         int snum;
4306         int n_services;
4307         union spoolss_PrinterInfo *info = NULL;
4308         uint32_t count = 0;
4309         WERROR result = WERR_OK;
4310         struct dcerpc_binding_handle *b = NULL;
4311         TALLOC_CTX *tmp_ctx = NULL;
4312
4313         tmp_ctx = talloc_new(mem_ctx);
4314         if (!tmp_ctx) {
4315                 return WERR_NOMEM;
4316         }
4317
4318         /*
4319          * printer shares are only updated on client enumeration. The background
4320          * printer process updates printer_list.tdb at regular intervals.
4321          */
4322         become_root();
4323         delete_and_reload_printers(server_event_context(), msg_ctx);
4324         unbecome_root();
4325
4326         n_services = lp_numservices();
4327         *count_p = 0;
4328         *info_p = NULL;
4329
4330         for (snum = 0; snum < n_services; snum++) {
4331
4332                 const char *printer;
4333                 struct spoolss_PrinterInfo2 *info2;
4334
4335                 if (!snum_is_shared_printer(snum)) {
4336                         continue;
4337                 }
4338
4339                 printer = lp_const_servicename(snum);
4340
4341                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4342                         printer, snum));
4343
4344                 if (b == NULL) {
4345                         result = winreg_printer_binding_handle(tmp_ctx,
4346                                                                session_info,
4347                                                                msg_ctx,
4348                                                                &b);
4349                         if (!W_ERROR_IS_OK(result)) {
4350                                 goto out;
4351                         }
4352                 }
4353
4354                 result = winreg_create_printer(tmp_ctx, b,
4355                                                printer);
4356                 if (!W_ERROR_IS_OK(result)) {
4357                         goto out;
4358                 }
4359
4360                 info = talloc_realloc(tmp_ctx, info,
4361                                             union spoolss_PrinterInfo,
4362                                             count + 1);
4363                 if (!info) {
4364                         result = WERR_NOMEM;
4365                         goto out;
4366                 }
4367
4368                 result = winreg_get_printer(tmp_ctx, b,
4369                                             printer, &info2);
4370                 if (!W_ERROR_IS_OK(result)) {
4371                         goto out;
4372                 }
4373
4374                 switch (level) {
4375                 case 0:
4376                         result = construct_printer_info0(info, session_info,
4377                                                          msg_ctx, info2,
4378                                                          servername,
4379                                                          &info[count].info0, snum);
4380                         break;
4381                 case 1:
4382                         result = construct_printer_info1(info, info2, flags,
4383                                                          servername,
4384                                                          &info[count].info1, snum);
4385                         break;
4386                 case 2:
4387                         result = construct_printer_info2(info, msg_ctx, info2,
4388                                                          servername,
4389                                                          &info[count].info2, snum);
4390                         break;
4391                 case 4:
4392                         result = construct_printer_info4(info, info2,
4393                                                          servername,
4394                                                          &info[count].info4, snum);
4395                         break;
4396                 case 5:
4397                         result = construct_printer_info5(info, info2,
4398                                                          servername,
4399                                                          &info[count].info5, snum);
4400                         break;
4401
4402                 default:
4403                         result = WERR_UNKNOWN_LEVEL;
4404                         goto out;
4405                 }
4406
4407                 if (!W_ERROR_IS_OK(result)) {
4408                         goto out;
4409                 }
4410
4411                 count++;
4412         }
4413
4414 out:
4415         if (W_ERROR_IS_OK(result)) {
4416                 *info_p = talloc_move(mem_ctx, &info);
4417                 *count_p = count;
4418         }
4419
4420         talloc_free(tmp_ctx);
4421
4422         return result;
4423 }
4424
4425 /********************************************************************
4426  * handle enumeration of printers at level 0
4427  ********************************************************************/
4428
4429 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4430                                   const struct auth_session_info *session_info,
4431                                   struct messaging_context *msg_ctx,
4432                                   uint32_t flags,
4433                                   const char *servername,
4434                                   union spoolss_PrinterInfo **info,
4435                                   uint32_t *count)
4436 {
4437         DEBUG(4,("enum_all_printers_info_0\n"));
4438
4439         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4440                                             servername, 0, flags, info, count);
4441 }
4442
4443
4444 /********************************************************************
4445 ********************************************************************/
4446
4447 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4448                                        const struct auth_session_info *session_info,
4449                                        struct messaging_context *msg_ctx,
4450                                        const char *servername,
4451                                        uint32_t flags,
4452                                        union spoolss_PrinterInfo **info,
4453                                        uint32_t *count)
4454 {
4455         DEBUG(4,("enum_all_printers_info_1\n"));
4456
4457         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4458                                             servername, 1, flags, info, count);
4459 }
4460
4461 /********************************************************************
4462  enum_all_printers_info_1_local.
4463 *********************************************************************/
4464
4465 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4466                                              const struct auth_session_info *session_info,
4467                                              struct messaging_context *msg_ctx,
4468                                              const char *servername,
4469                                              union spoolss_PrinterInfo **info,
4470                                              uint32_t *count)
4471 {
4472         DEBUG(4,("enum_all_printers_info_1_local\n"));
4473
4474         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4475                                         servername, PRINTER_ENUM_ICON8, info, count);
4476 }
4477
4478 /********************************************************************
4479  enum_all_printers_info_1_name.
4480 *********************************************************************/
4481
4482 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4483                                             const struct auth_session_info *session_info,
4484                                             struct messaging_context *msg_ctx,
4485                                             const char *servername,
4486                                             union spoolss_PrinterInfo **info,
4487                                             uint32_t *count)
4488 {
4489         const char *s = servername;
4490
4491         DEBUG(4,("enum_all_printers_info_1_name\n"));
4492
4493         if (servername != NULL &&
4494             (servername[0] == '\\') && (servername[1] == '\\')) {
4495                 s = servername + 2;
4496         }
4497
4498         if (!is_myname_or_ipaddr(s)) {
4499                 return WERR_INVALID_NAME;
4500         }
4501
4502         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4503                                         servername, PRINTER_ENUM_ICON8, info, count);
4504 }
4505
4506 /********************************************************************
4507  enum_all_printers_info_1_network.
4508 *********************************************************************/
4509
4510 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4511                                                const struct auth_session_info *session_info,
4512                                                struct messaging_context *msg_ctx,
4513                                                const char *servername,
4514                                                union spoolss_PrinterInfo **info,
4515                                                uint32_t *count)
4516 {
4517         const char *s = servername;
4518
4519         DEBUG(4,("enum_all_printers_info_1_network\n"));
4520
4521         /* If we respond to a enum_printers level 1 on our name with flags
4522            set to PRINTER_ENUM_REMOTE with a list of printers then these
4523            printers incorrectly appear in the APW browse list.
4524            Specifically the printers for the server appear at the workgroup
4525            level where all the other servers in the domain are
4526            listed. Windows responds to this call with a
4527            WERR_CAN_NOT_COMPLETE so we should do the same. */
4528
4529         if (servername != NULL &&
4530             (servername[0] == '\\') && (servername[1] == '\\')) {
4531                  s = servername + 2;
4532         }
4533
4534         if (is_myname_or_ipaddr(s)) {
4535                  return WERR_CAN_NOT_COMPLETE;
4536         }
4537
4538         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4539                                         servername, PRINTER_ENUM_NAME, info, count);
4540 }
4541
4542 /********************************************************************
4543  * api_spoolss_enumprinters
4544  *
4545  * called from api_spoolss_enumprinters (see this to understand)
4546  ********************************************************************/
4547
4548 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4549                                        const struct auth_session_info *session_info,
4550                                        struct messaging_context *msg_ctx,
4551                                        const char *servername,
4552                                        union spoolss_PrinterInfo **info,
4553                                        uint32_t *count)
4554 {
4555         DEBUG(4,("enum_all_printers_info_2\n"));
4556
4557         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4558                                             servername, 2, 0, info, count);
4559 }
4560
4561 /********************************************************************
4562  * handle enumeration of printers at level 1
4563  ********************************************************************/
4564
4565 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4566                                   const struct auth_session_info *session_info,
4567                                   struct messaging_context *msg_ctx,
4568                                   uint32_t flags,
4569                                   const char *servername,
4570                                   union spoolss_PrinterInfo **info,
4571                                   uint32_t *count)
4572 {
4573         /* Not all the flags are equals */
4574
4575         if (flags & PRINTER_ENUM_LOCAL) {
4576                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4577                                                       msg_ctx, servername, info, count);
4578         }
4579
4580         if (flags & PRINTER_ENUM_NAME) {
4581                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4582                                                      msg_ctx, servername, info,
4583                                                      count);
4584         }
4585
4586         if (flags & PRINTER_ENUM_NETWORK) {
4587                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4588                                                         msg_ctx, servername, info,
4589                                                         count);
4590         }
4591
4592         return WERR_OK; /* NT4sp5 does that */
4593 }
4594
4595 /********************************************************************
4596  * handle enumeration of printers at level 2
4597  ********************************************************************/
4598
4599 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4600                                   const struct auth_session_info *session_info,
4601                                   struct messaging_context *msg_ctx,
4602                                   uint32_t flags,
4603                                   const char *servername,
4604                                   union spoolss_PrinterInfo **info,
4605                                   uint32_t *count)
4606 {
4607         if (flags & PRINTER_ENUM_LOCAL) {
4608
4609                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4610                                                 servername,
4611                                                 info, count);
4612         }
4613
4614         if (flags & PRINTER_ENUM_NAME) {
4615                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4616                         return WERR_INVALID_NAME;
4617                 }
4618
4619                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4620                                                 servername,
4621                                                 info, count);
4622         }
4623
4624         if (flags & PRINTER_ENUM_REMOTE) {
4625                 return WERR_UNKNOWN_LEVEL;
4626         }
4627
4628         return WERR_OK;
4629 }
4630
4631 /********************************************************************
4632  * handle enumeration of printers at level 4
4633  ********************************************************************/
4634
4635 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4636                                   const struct auth_session_info *session_info,
4637                                   struct messaging_context *msg_ctx,
4638                                   uint32_t flags,
4639                                   const char *servername,
4640                                   union spoolss_PrinterInfo **info,
4641                                   uint32_t *count)
4642 {
4643         DEBUG(4,("enum_all_printers_info_4\n"));
4644
4645         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4646                                             servername, 4, flags, info, count);
4647 }
4648
4649
4650 /********************************************************************
4651  * handle enumeration of printers at level 5
4652  ********************************************************************/
4653
4654 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4655                                   const struct auth_session_info *session_info,
4656                                   struct messaging_context *msg_ctx,
4657                                   uint32_t flags,
4658                                   const char *servername,
4659                                   union spoolss_PrinterInfo **info,
4660                                   uint32_t *count)
4661 {
4662         DEBUG(4,("enum_all_printers_info_5\n"));
4663
4664         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4665                                             servername, 5, flags, info, count);
4666 }
4667
4668 /****************************************************************
4669  _spoolss_EnumPrinters
4670 ****************************************************************/
4671
4672 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4673                              struct spoolss_EnumPrinters *r)
4674 {
4675         const struct auth_session_info *session_info = get_session_info_system();
4676         WERROR result;
4677
4678         /* that's an [in out] buffer */
4679
4680         if (!r->in.buffer && (r->in.offered != 0)) {
4681                 return WERR_INVALID_PARAM;
4682         }
4683
4684         DEBUG(4,("_spoolss_EnumPrinters\n"));
4685
4686         *r->out.needed = 0;
4687         *r->out.count = 0;
4688         *r->out.info = NULL;
4689
4690         /*
4691          * Level 1:
4692          *          flags==PRINTER_ENUM_NAME
4693          *           if name=="" then enumerates all printers
4694          *           if name!="" then enumerate the printer
4695          *          flags==PRINTER_ENUM_REMOTE
4696          *          name is NULL, enumerate printers
4697          * Level 2: name!="" enumerates printers, name can't be NULL
4698          * Level 3: doesn't exist
4699          * Level 4: does a local registry lookup
4700          * Level 5: same as Level 2
4701          */
4702
4703         if (r->in.server && r->in.server[0] == '\0') {
4704                 r->in.server = NULL;
4705         }
4706
4707         switch (r->in.level) {
4708         case 0:
4709                 result = enumprinters_level0(p->mem_ctx, session_info,
4710                                              p->msg_ctx, r->in.flags,
4711                                              r->in.server,
4712                                              r->out.info, r->out.count);
4713                 break;
4714         case 1:
4715                 result = enumprinters_level1(p->mem_ctx, session_info,
4716                                              p->msg_ctx, r->in.flags,
4717                                              r->in.server,
4718                                              r->out.info, r->out.count);
4719                 break;
4720         case 2:
4721                 result = enumprinters_level2(p->mem_ctx, session_info,
4722                                              p->msg_ctx, r->in.flags,
4723                                              r->in.server,
4724                                              r->out.info, r->out.count);
4725                 break;
4726         case 4:
4727                 result = enumprinters_level4(p->mem_ctx, session_info,
4728                                              p->msg_ctx, r->in.flags,
4729                                              r->in.server,
4730                                              r->out.info, r->out.count);
4731                 break;
4732         case 5:
4733                 result = enumprinters_level5(p->mem_ctx, session_info,
4734                                              p->msg_ctx, r->in.flags,
4735                                              r->in.server,
4736                                              r->out.info, r->out.count);
4737                 break;
4738         default:
4739                 return WERR_UNKNOWN_LEVEL;
4740         }
4741
4742         if (!W_ERROR_IS_OK(result)) {
4743                 return result;
4744         }
4745
4746         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4747                                                      spoolss_EnumPrinters,
4748                                                      *r->out.info, r->in.level,
4749                                                      *r->out.count);
4750         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4751         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4752
4753         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4754 }
4755
4756 /****************************************************************
4757  _spoolss_GetPrinter
4758 ****************************************************************/
4759
4760 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4761                            struct spoolss_GetPrinter *r)
4762 {
4763         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4764         struct spoolss_PrinterInfo2 *info2 = NULL;
4765         WERROR result = WERR_OK;
4766         int snum;
4767
4768         /* that's an [in out] buffer */
4769
4770         if (!r->in.buffer && (r->in.offered != 0)) {
4771                 return WERR_INVALID_PARAM;
4772         }
4773
4774         *r->out.needed = 0;
4775
4776         if (Printer == NULL) {
4777                 return WERR_BADFID;
4778         }
4779
4780         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4781                 return WERR_BADFID;
4782         }
4783
4784         result = winreg_get_printer_internal(p->mem_ctx,
4785                                     get_session_info_system(),
4786                                     p->msg_ctx,
4787                                     lp_const_servicename(snum),
4788                                     &info2);
4789         if (!W_ERROR_IS_OK(result)) {
4790                 goto out;
4791         }
4792
4793         switch (r->in.level) {
4794         case 0:
4795                 result = construct_printer_info0(p->mem_ctx,
4796                                                  get_session_info_system(),
4797                                                  p->msg_ctx,
4798                                                  info2,
4799                                                  Printer->servername,
4800                                                  &r->out.info->info0,
4801                                                  snum);
4802                 break;
4803         case 1:
4804                 result = construct_printer_info1(p->mem_ctx, info2,
4805                                                  PRINTER_ENUM_ICON8,
4806                                                  Printer->servername,
4807                                                  &r->out.info->info1, snum);
4808                 break;
4809         case 2:
4810                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4811                                                  Printer->servername,
4812                                                  &r->out.info->info2, snum);
4813                 break;
4814         case 3:
4815                 result = construct_printer_info3(p->mem_ctx, info2,
4816                                                  Printer->servername,
4817                                                  &r->out.info->info3, snum);
4818                 break;
4819         case 4:
4820                 result = construct_printer_info4(p->mem_ctx, info2,
4821                                                  Printer->servername,
4822                                                  &r->out.info->info4, snum);
4823                 break;
4824         case 5:
4825                 result = construct_printer_info5(p->mem_ctx, info2,
4826                                                  Printer->servername,
4827                                                  &r->out.info->info5, snum);
4828                 break;
4829         case 6:
4830                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4831                                                  Printer->servername,
4832                                                  &r->out.info->info6, snum);
4833                 break;
4834         case 7:
4835                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4836                                                  Printer->servername,
4837                                                  &r->out.info->info7, snum);
4838                 break;
4839         case 8:
4840                 result = construct_printer_info8(p->mem_ctx, info2,
4841                                                  Printer->servername,
4842                                                  &r->out.info->info8, snum);
4843                 break;
4844         default:
4845                 result = WERR_UNKNOWN_LEVEL;
4846                 break;
4847         }
4848         TALLOC_FREE(info2);
4849
4850  out:
4851         if (!W_ERROR_IS_OK(result)) {
4852                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4853                           r->in.level, win_errstr(result)));
4854                 TALLOC_FREE(r->out.info);
4855                 return result;
4856         }
4857
4858         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4859                                                r->out.info, r->in.level);
4860         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4861
4862         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4863 }
4864
4865 /********************************************************************
4866  ********************************************************************/
4867
4868 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4869         do { \
4870                 if (in && strlen(in)) { \
4871                         out = talloc_strdup(mem_ctx, in); \
4872                 } else { \
4873                         out = talloc_strdup(mem_ctx, ""); \
4874                 } \
4875                 W_ERROR_HAVE_NO_MEMORY(out); \
4876         } while (0);
4877
4878 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4879         do { \
4880                 if (in && strlen(in)) { \
4881                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4882                 } else { \
4883                         out = talloc_strdup(mem_ctx, ""); \
4884                 } \
4885                 W_ERROR_HAVE_NO_MEMORY(out); \
4886         } while (0);
4887
4888 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4889                                                   const char **string_array,
4890                                                   const char ***presult,
4891                                                   const char *cservername,
4892                                                   const char *arch,
4893                                                   int version)
4894 {
4895         int i, num_strings = 0;
4896         const char **array = NULL;
4897
4898         if (string_array == NULL) {
4899                 return WERR_INVALID_PARAMETER;
4900         }
4901
4902         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4903                 const char *str = NULL;
4904
4905                 if (cservername == NULL || arch == NULL) {
4906                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4907                 } else {
4908                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4909                 }
4910
4911                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4912                         TALLOC_FREE(array);
4913                         return WERR_NOMEM;
4914                 }
4915         }
4916
4917         if (i > 0) {
4918                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4919                              &array, &num_strings);
4920         }
4921
4922         if (presult != NULL) {
4923                 *presult = array;
4924         } else {
4925                 talloc_free(array);
4926         }
4927
4928         return WERR_OK;
4929 }
4930
4931 /********************************************************************
4932  * fill a spoolss_DriverInfo1 struct
4933  ********************************************************************/
4934
4935 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4936                                         struct spoolss_DriverInfo1 *r,
4937                                         const struct spoolss_DriverInfo8 *driver,
4938                                         const char *servername)
4939 {
4940         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4941         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4942
4943         return WERR_OK;
4944 }
4945
4946 /********************************************************************
4947  * fill a spoolss_DriverInfo2 struct
4948  ********************************************************************/
4949
4950 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4951                                         struct spoolss_DriverInfo2 *r,
4952                                         const struct spoolss_DriverInfo8 *driver,
4953                                         const char *servername)
4954
4955 {
4956         const char *cservername = canon_servername(servername);
4957
4958         r->version              = driver->version;
4959
4960         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4961         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4962         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4963         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4964
4965         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4966                                driver->architecture,
4967                                driver->version,
4968                                driver->driver_path,
4969                                r->driver_path);
4970
4971         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4972                                driver->architecture,
4973                                driver->version,
4974                                driver->data_file,
4975                                r->data_file);
4976
4977         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4978                                driver->architecture,
4979                                driver->version,
4980                                driver->config_file,
4981                                r->config_file);
4982
4983         return WERR_OK;
4984 }
4985
4986 /********************************************************************
4987  * fill a spoolss_DriverInfo3 struct
4988  ********************************************************************/
4989
4990 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4991                                         struct spoolss_DriverInfo3 *r,
4992                                         const struct spoolss_DriverInfo8 *driver,
4993                                         const char *servername)
4994 {
4995         const char *cservername = canon_servername(servername);
4996
4997         r->version              = driver->version;
4998
4999         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5000         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5001         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5002         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5003
5004         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5005                                driver->architecture,
5006                                driver->version,
5007                                driver->driver_path,
5008                                r->driver_path);
5009
5010         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5011                                driver->architecture,
5012                                driver->version,
5013                                driver->data_file,
5014                                r->data_file);
5015
5016         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5017                                driver->architecture,
5018                                driver->version,
5019                                driver->config_file,
5020                                r->config_file);
5021
5022         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5023                                driver->architecture,
5024                                driver->version,
5025                                driver->help_file,
5026                                r->help_file);
5027
5028         FILL_DRIVER_STRING(mem_ctx,
5029                            driver->monitor_name,
5030                            r->monitor_name);
5031
5032         FILL_DRIVER_STRING(mem_ctx,
5033                            driver->default_datatype,
5034                            r->default_datatype);
5035
5036         return string_array_from_driver_info(mem_ctx,
5037                                              driver->dependent_files,
5038                                              &r->dependent_files,
5039                                              cservername,
5040                                              driver->architecture,
5041                                              driver->version);
5042 }
5043
5044 /********************************************************************
5045  * fill a spoolss_DriverInfo4 struct
5046  ********************************************************************/
5047
5048 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5049                                         struct spoolss_DriverInfo4 *r,
5050                                         const struct spoolss_DriverInfo8 *driver,
5051                                         const char *servername)
5052 {
5053         const char *cservername = canon_servername(servername);
5054         WERROR result;
5055
5056         r->version              = driver->version;
5057
5058         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5059         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5060         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5061         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5062
5063         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5064                                driver->architecture,
5065                                driver->version,
5066                                driver->driver_path,
5067                                r->driver_path);
5068
5069         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5070                                driver->architecture,
5071                                driver->version,
5072                                driver->data_file,
5073                                r->data_file);
5074
5075         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5076                                driver->architecture,
5077                                driver->version,
5078                                driver->config_file,
5079                                r->config_file);
5080
5081         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5082                                driver->architecture,
5083                                driver->version,
5084                                driver->help_file,
5085                                r->help_file);
5086
5087         result = string_array_from_driver_info(mem_ctx,
5088                                                driver->dependent_files,
5089                                                &r->dependent_files,
5090                                                cservername,
5091                                                driver->architecture,
5092                                                driver->version);
5093         if (!W_ERROR_IS_OK(result)) {
5094                 return result;
5095         }
5096
5097         FILL_DRIVER_STRING(mem_ctx,
5098                            driver->monitor_name,
5099                            r->monitor_name);
5100
5101         FILL_DRIVER_STRING(mem_ctx,
5102                            driver->default_datatype,
5103                            r->default_datatype);
5104
5105
5106         result = string_array_from_driver_info(mem_ctx,
5107                                                driver->previous_names,
5108                                                &r->previous_names,
5109                                                NULL, NULL, 0);
5110
5111         return result;
5112 }
5113
5114 /********************************************************************
5115  * fill a spoolss_DriverInfo5 struct
5116  ********************************************************************/
5117
5118 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5119                                         struct spoolss_DriverInfo5 *r,
5120                                         const struct spoolss_DriverInfo8 *driver,
5121                                         const char *servername)
5122 {
5123         const char *cservername = canon_servername(servername);
5124
5125         r->version              = driver->version;
5126
5127         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5128         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5129         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5130         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5131
5132         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5133                                driver->architecture,
5134                                driver->version,
5135                                driver->driver_path,
5136                                r->driver_path);
5137
5138         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5139                                driver->architecture,
5140                                driver->version,
5141                                driver->data_file,
5142                                r->data_file);
5143
5144         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5145                                driver->architecture,
5146                                driver->version,
5147                                driver->config_file,
5148                                r->config_file);
5149
5150         r->driver_attributes    = 0;
5151         r->config_version       = 0;
5152         r->driver_version       = 0;
5153
5154         return WERR_OK;
5155 }
5156 /********************************************************************
5157  * fill a spoolss_DriverInfo6 struct
5158  ********************************************************************/
5159
5160 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5161                                         struct spoolss_DriverInfo6 *r,
5162                                         const struct spoolss_DriverInfo8 *driver,
5163                                         const char *servername)
5164 {
5165         const char *cservername = canon_servername(servername);
5166         WERROR result;
5167
5168         r->version              = driver->version;
5169
5170         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5171         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5172         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5173         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5174
5175         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5176                                driver->architecture,
5177                                driver->version,
5178                                driver->driver_path,
5179                                r->driver_path);
5180
5181         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5182                                driver->architecture,
5183                                driver->version,
5184                                driver->data_file,
5185                                r->data_file);
5186
5187         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5188                                driver->architecture,
5189                                driver->version,
5190                                driver->config_file,
5191                                r->config_file);
5192
5193         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5194                                driver->architecture,
5195                                driver->version,
5196                                driver->help_file,
5197                                r->help_file);
5198
5199         FILL_DRIVER_STRING(mem_ctx,
5200                            driver->monitor_name,
5201                            r->monitor_name);
5202
5203         FILL_DRIVER_STRING(mem_ctx,
5204                            driver->default_datatype,
5205                            r->default_datatype);
5206
5207         result = string_array_from_driver_info(mem_ctx,
5208                                                driver->dependent_files,
5209                                                &r->dependent_files,
5210                                                cservername,
5211                                                driver->architecture,
5212                                                driver->version);
5213         if (!W_ERROR_IS_OK(result)) {
5214                 return result;
5215         }
5216
5217         result = string_array_from_driver_info(mem_ctx,
5218                                                driver->previous_names,
5219                                                &r->previous_names,
5220                                                NULL, NULL, 0);
5221         if (!W_ERROR_IS_OK(result)) {
5222                 return result;
5223         }
5224
5225         r->driver_date          = driver->driver_date;
5226         r->driver_version       = driver->driver_version;
5227
5228         FILL_DRIVER_STRING(mem_ctx,
5229                            driver->manufacturer_name,
5230                            r->manufacturer_name);
5231         FILL_DRIVER_STRING(mem_ctx,
5232                            driver->manufacturer_url,
5233                            r->manufacturer_url);
5234         FILL_DRIVER_STRING(mem_ctx,
5235                            driver->hardware_id,
5236                            r->hardware_id);
5237         FILL_DRIVER_STRING(mem_ctx,
5238                            driver->provider,
5239                            r->provider);
5240
5241         return WERR_OK;
5242 }
5243
5244 /********************************************************************
5245  * fill a spoolss_DriverInfo8 struct
5246  ********************************************************************/
5247
5248 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5249                                         struct spoolss_DriverInfo8 *r,
5250                                         const struct spoolss_DriverInfo8 *driver,
5251                                         const char *servername)
5252 {
5253         const char *cservername = canon_servername(servername);
5254         WERROR result;
5255
5256         r->version              = driver->version;
5257
5258         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5259         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5260         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5261         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5262
5263         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5264                                driver->architecture,
5265                                driver->version,
5266                                driver->driver_path,
5267                                r->driver_path);
5268
5269         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5270                                driver->architecture,
5271                                driver->version,
5272                                driver->data_file,
5273                                r->data_file);
5274
5275         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5276                                driver->architecture,
5277                                driver->version,
5278                                driver->config_file,
5279                                r->config_file);
5280
5281         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5282                                driver->architecture,
5283                                driver->version,
5284                                driver->help_file,
5285                                r->help_file);
5286
5287         FILL_DRIVER_STRING(mem_ctx,
5288                            driver->monitor_name,
5289                            r->monitor_name);
5290
5291         FILL_DRIVER_STRING(mem_ctx,
5292                            driver->default_datatype,
5293                            r->default_datatype);
5294
5295         result = string_array_from_driver_info(mem_ctx,
5296                                                driver->dependent_files,
5297                                                &r->dependent_files,
5298                                                cservername,
5299                                                driver->architecture,
5300                                                driver->version);
5301         if (!W_ERROR_IS_OK(result)) {
5302                 return result;
5303         }
5304
5305         result = string_array_from_driver_info(mem_ctx,
5306                                                driver->previous_names,
5307                                                &r->previous_names,
5308                                                NULL, NULL, 0);
5309         if (!W_ERROR_IS_OK(result)) {
5310                 return result;
5311         }
5312
5313         r->driver_date          = driver->driver_date;
5314         r->driver_version       = driver->driver_version;
5315
5316         FILL_DRIVER_STRING(mem_ctx,
5317                            driver->manufacturer_name,
5318                            r->manufacturer_name);
5319         FILL_DRIVER_STRING(mem_ctx,
5320                            driver->manufacturer_url,
5321                            r->manufacturer_url);
5322         FILL_DRIVER_STRING(mem_ctx,
5323                            driver->hardware_id,
5324                            r->hardware_id);
5325         FILL_DRIVER_STRING(mem_ctx,
5326                            driver->provider,
5327                            r->provider);
5328
5329         FILL_DRIVER_STRING(mem_ctx,
5330                            driver->print_processor,
5331                            r->print_processor);
5332         FILL_DRIVER_STRING(mem_ctx,
5333                            driver->vendor_setup,
5334                            r->vendor_setup);
5335
5336         result = string_array_from_driver_info(mem_ctx,
5337                                                driver->color_profiles,
5338                                                &r->color_profiles,
5339                                                NULL, NULL, 0);
5340         if (!W_ERROR_IS_OK(result)) {
5341                 return result;
5342         }
5343
5344         FILL_DRIVER_STRING(mem_ctx,
5345                            driver->inf_path,
5346                            r->inf_path);
5347
5348         r->printer_driver_attributes    = driver->printer_driver_attributes;
5349
5350         result = string_array_from_driver_info(mem_ctx,
5351                                                driver->core_driver_dependencies,
5352                                                &r->core_driver_dependencies,
5353                                                NULL, NULL, 0);
5354         if (!W_ERROR_IS_OK(result)) {
5355                 return result;
5356         }
5357
5358         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5359         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5360
5361         return WERR_OK;
5362 }
5363
5364 #if 0 /* disabled until marshalling issues are resolved - gd */
5365 /********************************************************************
5366  ********************************************************************/
5367
5368 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5369                                           struct spoolss_DriverFileInfo *r,
5370                                           const char *cservername,
5371                                           const char *file_name,
5372                                           enum spoolss_DriverFileType file_type,
5373                                           uint32_t file_version)
5374 {
5375         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5376                                           cservername, file_name);
5377         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5378         r->file_type    = file_type;
5379         r->file_version = file_version;
5380
5381         return WERR_OK;
5382 }
5383
5384 /********************************************************************
5385  ********************************************************************/
5386
5387 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5388                                                  const struct spoolss_DriverInfo8 *driver,
5389                                                  const char *cservername,
5390                                                  struct spoolss_DriverFileInfo **info_p,
5391                                                  uint32_t *count_p)
5392 {
5393         struct spoolss_DriverFileInfo *info = NULL;
5394         uint32_t count = 0;
5395         WERROR result;
5396         uint32_t i;
5397
5398         *info_p = NULL;
5399         *count_p = 0;
5400
5401         if (strlen(driver->driver_path)) {
5402                 info = talloc_realloc(mem_ctx, info,
5403                                             struct spoolss_DriverFileInfo,
5404                                             count + 1);
5405                 W_ERROR_HAVE_NO_MEMORY(info);
5406                 result = fill_spoolss_DriverFileInfo(info,
5407                                                      &info[count],
5408                                                      cservername,
5409                                                      driver->driver_path,
5410                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5411                                                      0);
5412                 W_ERROR_NOT_OK_RETURN(result);
5413                 count++;
5414         }
5415
5416         if (strlen(driver->config_file)) {
5417                 info = talloc_realloc(mem_ctx, info,
5418                                             struct spoolss_DriverFileInfo,
5419                                             count + 1);
5420                 W_ERROR_HAVE_NO_MEMORY(info);
5421                 result = fill_spoolss_DriverFileInfo(info,
5422                                                      &info[count],
5423                                                      cservername,
5424                                                      driver->config_file,
5425                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5426                                                      0);
5427                 W_ERROR_NOT_OK_RETURN(result);
5428                 count++;
5429         }
5430
5431         if (strlen(driver->data_file)) {
5432                 info = talloc_realloc(mem_ctx, info,
5433                                             struct spoolss_DriverFileInfo,
5434                                             count + 1);
5435                 W_ERROR_HAVE_NO_MEMORY(info);
5436                 result = fill_spoolss_DriverFileInfo(info,
5437                                                      &info[count],
5438                                                      cservername,
5439                                                      driver->data_file,
5440                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5441                                                      0);
5442                 W_ERROR_NOT_OK_RETURN(result);
5443                 count++;
5444         }
5445
5446         if (strlen(driver->help_file)) {
5447                 info = talloc_realloc(mem_ctx, info,
5448                                             struct spoolss_DriverFileInfo,
5449                                             count + 1);
5450                 W_ERROR_HAVE_NO_MEMORY(info);
5451                 result = fill_spoolss_DriverFileInfo(info,
5452                                                      &info[count],
5453                                                      cservername,
5454                                                      driver->help_file,
5455                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5456                                                      0);
5457                 W_ERROR_NOT_OK_RETURN(result);
5458                 count++;
5459         }
5460
5461         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5462                 info = talloc_realloc(mem_ctx, info,
5463                                             struct spoolss_DriverFileInfo,
5464                                             count + 1);
5465                 W_ERROR_HAVE_NO_MEMORY(info);
5466                 result = fill_spoolss_DriverFileInfo(info,
5467                                                      &info[count],
5468                                                      cservername,
5469                                                      driver->dependent_files[i],
5470                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5471                                                      0);
5472                 W_ERROR_NOT_OK_RETURN(result);
5473                 count++;
5474         }
5475
5476         *info_p = info;
5477         *count_p = count;
5478
5479         return WERR_OK;
5480 }
5481
5482 /********************************************************************
5483  * fill a spoolss_DriverInfo101 struct
5484  ********************************************************************/
5485
5486 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5487                                           struct spoolss_DriverInfo101 *r,
5488                                           const struct spoolss_DriverInfo8 *driver,
5489                                           const char *servername)
5490 {
5491         const char *cservername = canon_servername(servername);
5492         WERROR result;
5493
5494         r->version              = driver->version;
5495
5496         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5497         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5498         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5499         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5500
5501         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5502                                                     cservername,
5503                                                     &r->file_info,
5504                                                     &r->file_count);
5505         if (!W_ERROR_IS_OK(result)) {
5506                 return result;
5507         }
5508
5509         FILL_DRIVER_STRING(mem_ctx,
5510                            driver->monitor_name,
5511                            r->monitor_name);
5512
5513         FILL_DRIVER_STRING(mem_ctx,
5514                            driver->default_datatype,
5515                            r->default_datatype);
5516
5517         result = string_array_from_driver_info(mem_ctx,
5518                                                driver->previous_names,
5519                                                &r->previous_names,
5520                                                NULL, NULL, 0);
5521         if (!W_ERROR_IS_OK(result)) {
5522                 return result;
5523         }
5524
5525         r->driver_date          = driver->driver_date;
5526         r->driver_version       = driver->driver_version;
5527
5528         FILL_DRIVER_STRING(mem_ctx,
5529                            driver->manufacturer_name,
5530                            r->manufacturer_name);
5531         FILL_DRIVER_STRING(mem_ctx,
5532                            driver->manufacturer_url,
5533                            r->manufacturer_url);
5534         FILL_DRIVER_STRING(mem_ctx,
5535                            driver->hardware_id,
5536                            r->hardware_id);
5537         FILL_DRIVER_STRING(mem_ctx,
5538                            driver->provider,
5539                            r->provider);
5540
5541         return WERR_OK;
5542 }
5543 #endif
5544 /********************************************************************
5545  ********************************************************************/
5546
5547 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5548                                                   const struct auth_session_info *session_info,
5549                                                   struct messaging_context *msg_ctx,
5550                                                   uint32_t level,
5551                                                   union spoolss_DriverInfo *r,
5552                                                   int snum,
5553                                                   const char *servername,
5554                                                   const char *architecture,
5555                                                   uint32_t version)
5556 {
5557         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5558         struct spoolss_DriverInfo8 *driver;
5559         WERROR result;
5560         struct dcerpc_binding_handle *b;
5561         TALLOC_CTX *tmp_ctx = NULL;
5562
5563         if (level == 101) {
5564                 return WERR_UNKNOWN_LEVEL;
5565         }
5566
5567         tmp_ctx = talloc_new(mem_ctx);
5568         if (!tmp_ctx) {
5569                 return WERR_NOMEM;
5570         }
5571
5572         result = winreg_printer_binding_handle(tmp_ctx,
5573                                                session_info,
5574                                                msg_ctx,
5575                                                &b);
5576         if (!W_ERROR_IS_OK(result)) {
5577                 goto done;
5578         }
5579
5580         result = winreg_get_printer(tmp_ctx, b,
5581                                     lp_const_servicename(snum),
5582                                     &pinfo2);
5583
5584         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5585                 win_errstr(result)));
5586
5587         if (!W_ERROR_IS_OK(result)) {
5588                 result = WERR_INVALID_PRINTER_NAME;
5589                 goto done;
5590         }
5591
5592         result = winreg_get_driver(tmp_ctx, b,
5593                                    architecture,
5594                                    pinfo2->drivername, version, &driver);
5595
5596         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5597                 win_errstr(result)));
5598
5599         if (!W_ERROR_IS_OK(result)) {
5600                 /*
5601                  * Is this a W2k client ?
5602                  */
5603
5604                 if (version < 3) {
5605                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5606                         goto done;
5607                 }
5608
5609                 /* Yes - try again with a WinNT driver. */
5610                 version = 2;
5611                 result = winreg_get_driver(tmp_ctx, b,
5612                                            architecture,
5613                                            pinfo2->drivername,
5614                                            version, &driver);
5615                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5616                         win_errstr(result)));
5617                 if (!W_ERROR_IS_OK(result)) {
5618                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5619                         goto done;
5620                 }
5621         }
5622
5623         /* these are allocated on mem_ctx and not tmp_ctx because they are
5624          * the 'return value' and need to utlive this call */
5625         switch (level) {
5626         case 1:
5627                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5628                 break;
5629         case 2:
5630                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5631                 break;
5632         case 3:
5633                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5634                 break;
5635         case 4:
5636                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5637                 break;
5638         case 5:
5639                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5640                 break;
5641         case 6:
5642                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5643                 break;
5644         case 8:
5645                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5646                 break;
5647 #if 0 /* disabled until marshalling issues are resolved - gd */
5648         case 101:
5649                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5650                 break;
5651 #endif
5652         default:
5653                 result = WERR_UNKNOWN_LEVEL;
5654                 break;
5655         }
5656
5657 done:
5658         talloc_free(tmp_ctx);
5659         return result;
5660 }
5661
5662 /****************************************************************
5663  _spoolss_GetPrinterDriver2
5664 ****************************************************************/
5665
5666 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5667                                   struct spoolss_GetPrinterDriver2 *r)
5668 {
5669         struct printer_handle *printer;
5670         WERROR result;
5671         uint32_t version = r->in.client_major_version;
5672
5673         int snum;
5674
5675         /* that's an [in out] buffer */
5676
5677         if (!r->in.buffer && (r->in.offered != 0)) {
5678                 return WERR_INVALID_PARAM;
5679         }
5680
5681         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5682
5683         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5684                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5685                 return WERR_INVALID_PRINTER_NAME;
5686         }
5687
5688         *r->out.needed = 0;
5689         *r->out.server_major_version = 0;
5690         *r->out.server_minor_version = 0;
5691
5692         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5693                 return WERR_BADFID;
5694         }
5695
5696         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5697                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5698                         "downgrading to v3\n"));
5699                 version = SPOOLSS_DRIVER_VERSION_200X;
5700         }
5701
5702         result = construct_printer_driver_info_level(p->mem_ctx,
5703                                                      get_session_info_system(),
5704                                                      p->msg_ctx,
5705                                                      r->in.level, r->out.info,
5706                                                      snum, printer->servername,
5707                                                      r->in.architecture,
5708                                                      version);
5709         if (!W_ERROR_IS_OK(result)) {
5710                 TALLOC_FREE(r->out.info);
5711                 return result;
5712         }
5713
5714         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5715                                                r->out.info, r->in.level);
5716         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5717
5718         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5719 }
5720
5721
5722 /****************************************************************
5723  _spoolss_StartPagePrinter
5724 ****************************************************************/
5725
5726 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5727                                  struct spoolss_StartPagePrinter *r)
5728 {
5729         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5730
5731         if (!Printer) {
5732                 DEBUG(3,("_spoolss_StartPagePrinter: "
5733                         "Error in startpageprinter printer handle\n"));
5734                 return WERR_BADFID;
5735         }
5736
5737         Printer->page_started = true;
5738         return WERR_OK;
5739 }
5740
5741 /****************************************************************
5742  _spoolss_EndPagePrinter
5743 ****************************************************************/
5744
5745 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5746                                struct spoolss_EndPagePrinter *r)
5747 {
5748         int snum;
5749
5750         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5751
5752         if (!Printer) {
5753                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5754                         OUR_HANDLE(r->in.handle)));
5755                 return WERR_BADFID;
5756         }
5757
5758         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5759                 return WERR_BADFID;
5760
5761         Printer->page_started = false;
5762         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5763
5764         return WERR_OK;
5765 }
5766
5767 /****************************************************************
5768  _spoolss_StartDocPrinter
5769 ****************************************************************/
5770
5771 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5772                                 struct spoolss_StartDocPrinter *r)
5773 {
5774         struct spoolss_DocumentInfo1 *info_1;
5775         int snum;
5776         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5777         WERROR werr;
5778         char *rhost;
5779         int rc;
5780
5781         if (!Printer) {
5782                 DEBUG(2,("_spoolss_StartDocPrinter: "
5783                         "Invalid handle (%s:%u:%u)\n",
5784                         OUR_HANDLE(r->in.handle)));
5785                 return WERR_BADFID;
5786         }
5787
5788         if (Printer->jobid) {
5789                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5790                           "StartDocPrinter called twice! "
5791                           "(existing jobid = %d)\n", Printer->jobid));
5792                 return WERR_INVALID_HANDLE;
5793         }
5794
5795         if (r->in.info_ctr->level != 1) {
5796                 return WERR_UNKNOWN_LEVEL;
5797         }
5798
5799         info_1 = r->in.info_ctr->info.info1;
5800
5801         /*
5802          * a nice thing with NT is it doesn't listen to what you tell it.
5803          * when asked to send _only_ RAW datas, it tries to send datas
5804          * in EMF format.
5805          *
5806          * So I add checks like in NT Server ...
5807          */
5808
5809         if (info_1->datatype) {
5810                 /*
5811                  * The v4 driver model used in Windows 8 declares print jobs
5812                  * intended to bypass the XPS processing layer by setting
5813                  * datatype to "XPS_PASS" instead of "RAW".
5814                  */
5815                 if ((strcmp(info_1->datatype, "RAW") != 0)
5816                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5817                         *r->out.job_id = 0;
5818                         return WERR_INVALID_DATATYPE;
5819                 }
5820         }
5821
5822         /* get the share number of the printer */
5823         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5824                 return WERR_BADFID;
5825         }
5826
5827         rc = get_remote_hostname(p->remote_address,
5828                                  &rhost,
5829                                  p->mem_ctx);
5830         if (rc < 0) {
5831                 return WERR_NOMEM;
5832         }
5833         if (strequal(rhost,"UNKNOWN")) {
5834                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5835                                                          p->mem_ctx);
5836                 if (rhost == NULL) {
5837                         return WERR_NOMEM;
5838                 }
5839         }
5840
5841         werr = print_job_start(p->session_info,
5842                                p->msg_ctx,
5843                                rhost,
5844                                snum,
5845                                info_1->document_name,
5846                                info_1->output_file,
5847                                Printer->devmode,
5848                                &Printer->jobid);
5849
5850         /* An error occured in print_job_start() so return an appropriate
5851            NT error code. */
5852
5853         if (!W_ERROR_IS_OK(werr)) {
5854                 return werr;
5855         }
5856
5857         Printer->document_started = true;
5858         *r->out.job_id = Printer->jobid;
5859
5860         return WERR_OK;
5861 }
5862
5863 /****************************************************************
5864  _spoolss_EndDocPrinter
5865 ****************************************************************/
5866
5867 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5868                               struct spoolss_EndDocPrinter *r)
5869 {
5870         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5871         NTSTATUS status;
5872         int snum;
5873
5874         if (!Printer) {
5875                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5876                         OUR_HANDLE(r->in.handle)));
5877                 return WERR_BADFID;
5878         }
5879
5880         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5881                 return WERR_BADFID;
5882         }
5883
5884         Printer->document_started = false;
5885         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5886         if (!NT_STATUS_IS_OK(status)) {
5887                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5888                           "print_job_end failed [%s]\n",
5889                           nt_errstr(status)));
5890         }
5891
5892         Printer->jobid = 0;
5893         return ntstatus_to_werror(status);
5894 }
5895
5896 /****************************************************************
5897  _spoolss_WritePrinter
5898 ****************************************************************/
5899
5900 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5901                              struct spoolss_WritePrinter *r)
5902 {
5903         ssize_t buffer_written;
5904         int snum;
5905         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5906
5907         if (!Printer) {
5908                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5909                         OUR_HANDLE(r->in.handle)));
5910                 *r->out.num_written = r->in._data_size;
5911                 return WERR_BADFID;
5912         }
5913
5914         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5915                 return WERR_BADFID;
5916
5917         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5918         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5919                                                    snum, Printer->jobid,
5920                                                    (const char *)r->in.data.data,
5921                                                    (size_t)r->in._data_size);
5922         if (buffer_written == (ssize_t)-1) {
5923                 *r->out.num_written = 0;
5924                 if (errno == ENOSPC)
5925                         return WERR_NO_SPOOL_SPACE;
5926                 else
5927                         return WERR_ACCESS_DENIED;
5928         }
5929
5930         *r->out.num_written = r->in._data_size;
5931
5932         return WERR_OK;
5933 }
5934
5935 /********************************************************************
5936  * api_spoolss_getprinter
5937  * called from the spoolss dispatcher
5938  *
5939  ********************************************************************/
5940
5941 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5942                               struct pipes_struct *p)
5943 {
5944         const struct auth_session_info *session_info = p->session_info;
5945         int snum;
5946         WERROR errcode = WERR_BADFUNC;
5947         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5948
5949         if (!Printer) {
5950                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5951                         OUR_HANDLE(handle)));
5952                 return WERR_BADFID;
5953         }
5954
5955         if (!get_printer_snum(p, handle, &snum, NULL))
5956                 return WERR_BADFID;
5957
5958         switch (command) {
5959         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5960                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5961                 break;
5962         case SPOOLSS_PRINTER_CONTROL_RESUME:
5963         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5964                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5965                 break;
5966         case SPOOLSS_PRINTER_CONTROL_PURGE:
5967                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5968                 break;
5969         default:
5970                 return WERR_UNKNOWN_LEVEL;
5971         }
5972
5973         return errcode;
5974 }
5975
5976
5977 /****************************************************************
5978  _spoolss_AbortPrinter
5979  * From MSDN: "Deletes printer's spool file if printer is configured
5980  * for spooling"
5981 ****************************************************************/
5982
5983 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5984                              struct spoolss_AbortPrinter *r)
5985 {
5986         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5987         int             snum;
5988         WERROR          errcode = WERR_OK;
5989
5990         if (!Printer) {
5991                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5992                         OUR_HANDLE(r->in.handle)));
5993                 return WERR_BADFID;
5994         }
5995
5996         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5997                 return WERR_BADFID;
5998
5999         if (!Printer->document_started) {
6000                 return WERR_SPL_NO_STARTDOC;
6001         }
6002
6003         errcode = print_job_delete(p->session_info,
6004                                    p->msg_ctx,
6005                                    snum,
6006                                    Printer->jobid);
6007
6008         return errcode;
6009 }
6010
6011 /********************************************************************
6012  * called by spoolss_api_setprinter
6013  * when updating a printer description
6014  ********************************************************************/
6015
6016 static WERROR update_printer_sec(struct policy_handle *handle,
6017                                  struct pipes_struct *p,
6018                                  struct sec_desc_buf *secdesc_ctr)
6019 {
6020         struct spoolss_security_descriptor *new_secdesc = NULL;
6021         struct spoolss_security_descriptor *old_secdesc = NULL;
6022         const char *printer;
6023         WERROR result;
6024         int snum;
6025         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6026         struct dcerpc_binding_handle *b;
6027         TALLOC_CTX *tmp_ctx = NULL;
6028
6029         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6030                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6031                          OUR_HANDLE(handle)));
6032
6033                 result = WERR_BADFID;
6034                 goto done;
6035         }
6036
6037         if (secdesc_ctr == NULL) {
6038                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6039                 result = WERR_INVALID_PARAM;
6040                 goto done;
6041         }
6042         printer = lp_const_servicename(snum);
6043
6044         /* Check the user has permissions to change the security
6045            descriptor.  By experimentation with two NT machines, the user
6046            requires Full Access to the printer to change security
6047            information. */
6048
6049         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6050                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6051                 result = WERR_ACCESS_DENIED;
6052                 goto done;
6053         }
6054
6055         tmp_ctx = talloc_new(p->mem_ctx);
6056         if (!tmp_ctx) {
6057                 return WERR_NOMEM;
6058         }
6059
6060         result = winreg_printer_binding_handle(tmp_ctx,
6061                                                get_session_info_system(),
6062                                                p->msg_ctx,
6063                                                &b);
6064         if (!W_ERROR_IS_OK(result)) {
6065                 goto done;
6066         }
6067
6068         /* NT seems to like setting the security descriptor even though
6069            nothing may have actually changed. */
6070         result = winreg_get_printer_secdesc(tmp_ctx, b,
6071                                             printer,
6072                                             &old_secdesc);
6073         if (!W_ERROR_IS_OK(result)) {
6074                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6075                 result = WERR_BADFID;
6076                 goto done;
6077         }
6078
6079         if (DEBUGLEVEL >= 10) {
6080                 struct security_acl *the_acl;
6081                 int i;
6082
6083                 the_acl = old_secdesc->dacl;
6084                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6085                            printer, the_acl->num_aces));
6086
6087                 for (i = 0; i < the_acl->num_aces; i++) {
6088                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6089                                            &the_acl->aces[i].trustee),
6090                                   the_acl->aces[i].access_mask));
6091                 }
6092
6093                 the_acl = secdesc_ctr->sd->dacl;
6094
6095                 if (the_acl) {
6096                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6097                                    printer, the_acl->num_aces));
6098
6099                         for (i = 0; i < the_acl->num_aces; i++) {
6100                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6101                                                    &the_acl->aces[i].trustee),
6102                                            the_acl->aces[i].access_mask));
6103                         }
6104                 } else {
6105                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6106                 }
6107         }
6108
6109         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6110         if (new_secdesc == NULL) {
6111                 result = WERR_NOMEM;
6112                 goto done;
6113         }
6114
6115         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6116                 result = WERR_OK;
6117                 goto done;
6118         }
6119
6120         result = winreg_set_printer_secdesc(tmp_ctx, b,
6121                                             printer,
6122                                             new_secdesc);
6123
6124 done:
6125         talloc_free(tmp_ctx);
6126         return result;
6127 }
6128
6129 /********************************************************************
6130  Canonicalize printer info from a client
6131  ********************************************************************/
6132
6133 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6134                              struct spoolss_SetPrinterInfo2 *info2,
6135                              int snum)
6136 {
6137         fstring printername;
6138         const char *p;
6139
6140         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6141                 "portname=%s drivername=%s comment=%s location=%s\n",
6142                 info2->servername, info2->printername, info2->sharename,
6143                 info2->portname, info2->drivername, info2->comment,
6144                 info2->location));
6145
6146         /* we force some elements to "correct" values */
6147         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6148         if (info2->servername == NULL) {
6149                 return false;
6150         }
6151         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6152         if (info2->sharename == NULL) {
6153                 return false;
6154         }
6155
6156         /* check to see if we allow printername != sharename */
6157         if (lp_force_printername(snum)) {
6158                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6159                                         lp_netbios_name(), info2->sharename);
6160         } else {
6161                 /* make sure printername is in \\server\printername format */
6162                 fstrcpy(printername, info2->printername);
6163                 p = printername;
6164                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6165                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6166                                 p++;
6167                 }
6168
6169                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6170                                         lp_netbios_name(), p);
6171         }
6172         if (info2->printername == NULL) {
6173                 return false;
6174         }
6175
6176         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6177         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6178
6179         return true;
6180 }
6181
6182 /****************************************************************************
6183 ****************************************************************************/
6184
6185 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6186 {
6187         char *cmd = lp_addport_command(talloc_tos());
6188         char *command = NULL;
6189         int ret;
6190         bool is_print_op = false;
6191
6192         if ( !*cmd ) {
6193                 return WERR_ACCESS_DENIED;
6194         }
6195
6196         command = talloc_asprintf(ctx,
6197                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6198         if (!command) {
6199                 return WERR_NOMEM;
6200         }
6201
6202         if ( token )
6203                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6204
6205         DEBUG(10,("Running [%s]\n", command));
6206
6207         /********* BEGIN SePrintOperatorPrivilege **********/
6208
6209         if ( is_print_op )
6210                 become_root();
6211
6212         ret = smbrun(command, NULL);
6213
6214         if ( is_print_op )
6215                 unbecome_root();
6216
6217         /********* END SePrintOperatorPrivilege **********/
6218
6219         DEBUGADD(10,("returned [%d]\n", ret));
6220
6221         TALLOC_FREE(command);
6222
6223         if ( ret != 0 ) {
6224                 return WERR_ACCESS_DENIED;
6225         }
6226
6227         return WERR_OK;
6228 }
6229
6230 /****************************************************************************
6231 ****************************************************************************/
6232
6233 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6234                                    int snum)
6235 {
6236         /*
6237          * As we do not know if we are embedded in the file server process
6238          * or not, we have to pretend that all shares are in use.
6239          */
6240         return true;
6241 }
6242
6243 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6244                              struct spoolss_SetPrinterInfo2 *info2,
6245                              const char *remote_machine,
6246                              struct messaging_context *msg_ctx)
6247 {
6248         char *cmd = lp_addprinter_command(talloc_tos());
6249         char **qlines;
6250         char *command = NULL;
6251         int numlines;
6252         int ret;
6253         int fd;
6254         bool is_print_op = false;
6255
6256         if (!remote_machine) {
6257                 return false;
6258         }
6259
6260         command = talloc_asprintf(ctx,
6261                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6262                         cmd, info2->printername, info2->sharename,
6263                         info2->portname, info2->drivername,
6264                         info2->location, info2->comment, remote_machine);
6265         if (!command) {
6266                 return false;
6267         }
6268
6269         if ( token )
6270                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6271
6272         DEBUG(10,("Running [%s]\n", command));
6273
6274         /********* BEGIN SePrintOperatorPrivilege **********/
6275
6276         if ( is_print_op )
6277                 become_root();
6278
6279         if ( (ret = smbrun(command, &fd)) == 0 ) {
6280                 /* Tell everyone we updated smb.conf. */
6281                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6282         }
6283
6284         if ( is_print_op )
6285                 unbecome_root();
6286
6287         /********* END SePrintOperatorPrivilege **********/
6288
6289         DEBUGADD(10,("returned [%d]\n", ret));
6290
6291         TALLOC_FREE(command);
6292
6293         if ( ret != 0 ) {
6294                 if (fd != -1)
6295                         close(fd);
6296                 return false;
6297         }
6298
6299         /* reload our services immediately */
6300         become_root();
6301         reload_services(NULL, spoolss_conn_snum_used, false);
6302         unbecome_root();
6303
6304         numlines = 0;
6305         /* Get lines and convert them back to dos-codepage */
6306         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6307         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6308         close(fd);
6309
6310         /* Set the portname to what the script says the portname should be. */
6311         /* but don't require anything to be return from the script exit a good error code */
6312
6313         if (numlines) {
6314                 /* Set the portname to what the script says the portname should be. */
6315                 info2->portname = talloc_strdup(ctx, qlines[0]);
6316                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6317         }
6318
6319         TALLOC_FREE(qlines);
6320         return true;
6321 }
6322
6323 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6324                                const struct auth_session_info *session_info,
6325                                struct messaging_context *msg_ctx,
6326                                int snum,
6327                                struct spoolss_SetPrinterInfo2 *printer,
6328                                struct spoolss_PrinterInfo2 *old_printer)
6329 {
6330         bool force_update = (old_printer == NULL);
6331         const char *dnsdomname;
6332         const char *longname;
6333         const char *uncname;
6334         const char *spooling;
6335         DATA_BLOB buffer;
6336         WERROR result = WERR_OK;
6337         struct dcerpc_binding_handle *b;
6338         TALLOC_CTX *tmp_ctx;
6339         bool ok;
6340
6341         tmp_ctx = talloc_new(mem_ctx);
6342         if (!tmp_ctx) {
6343                 return WERR_NOMEM;
6344         }
6345
6346         result = winreg_printer_binding_handle(tmp_ctx,
6347                                                session_info,
6348                                                msg_ctx,
6349                                                &b);
6350         if (!W_ERROR_IS_OK(result)) {
6351                 goto done;
6352         }
6353
6354         if (printer->drivername != NULL &&
6355             (force_update ||
6356              !strequal(printer->drivername, old_printer->drivername))) {
6357                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6358                 if (!ok) {
6359                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6360                         result = WERR_INVALID_DATA;
6361                         goto done;
6362                 }
6363                 result = winreg_set_printer_dataex(tmp_ctx, b,
6364                                           printer->sharename,
6365                                           SPOOL_DSSPOOLER_KEY,
6366                                           SPOOL_REG_DRIVERNAME,
6367                                           REG_SZ,
6368                                           buffer.data,
6369                                           buffer.length);
6370                 if (!W_ERROR_IS_OK(result)) {
6371                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6372                         goto done;
6373                 }
6374
6375                 if (!force_update) {
6376                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6377                                 printer->drivername));
6378
6379                         notify_printer_driver(server_event_context(), msg_ctx,
6380                                               snum, printer->drivername ?
6381                                               printer->drivername : "");
6382                 }
6383         }
6384
6385         if (printer->comment != NULL &&
6386             (force_update ||
6387              !strequal(printer->comment, old_printer->comment))) {
6388                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6389                 if (!ok) {
6390                         DEBUG(0, ("comment data corrupted\n"));
6391                         result = WERR_INVALID_DATA;
6392                         goto done;
6393                 }
6394                 result = winreg_set_printer_dataex(tmp_ctx, b,
6395                                           printer->sharename,
6396                                           SPOOL_DSSPOOLER_KEY,
6397                                           SPOOL_REG_DESCRIPTION,
6398                                           REG_SZ,
6399                                           buffer.data,
6400                                           buffer.length);
6401                 if (!W_ERROR_IS_OK(result)) {
6402                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6403                         goto done;
6404                 }
6405
6406                 if (!force_update) {
6407                         notify_printer_comment(server_event_context(), msg_ctx,
6408                                                snum, printer->comment ?
6409                                                printer->comment : "");
6410                 }
6411         }
6412
6413         if (printer->sharename != NULL &&
6414             (force_update ||
6415              !strequal(printer->sharename, old_printer->sharename))) {
6416                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6417                 if (!ok) {
6418                         DEBUG(0, ("sharename data corrupted\n"));
6419                         result = WERR_INVALID_DATA;
6420                         goto done;
6421                 }
6422                 result = winreg_set_printer_dataex(tmp_ctx, b,
6423                                           printer->sharename,
6424                                           SPOOL_DSSPOOLER_KEY,
6425                                           SPOOL_REG_PRINTSHARENAME,
6426                                           REG_SZ,
6427                                           buffer.data,
6428                                           buffer.length);
6429                 if (!W_ERROR_IS_OK(result)) {
6430                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6431                         goto done;
6432                 }
6433
6434                 if (!force_update) {
6435                         notify_printer_sharename(server_event_context(),
6436                                                  msg_ctx,
6437                                                  snum, printer->sharename ?
6438                                                  printer->sharename : "");
6439                 }
6440         }
6441
6442         if (printer->printername != NULL &&
6443             (force_update ||
6444              !strequal(printer->printername, old_printer->printername))) {
6445                 const char *p;
6446
6447                 p = strrchr(printer->printername, '\\' );
6448                 if (p != NULL) {
6449                         p++;
6450                 } else {
6451                         p = printer->printername;
6452                 }
6453
6454                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6455                 if (!ok) {
6456                         DEBUG(0, ("printername data corrupted\n"));
6457                         result = WERR_INVALID_DATA;
6458                         goto done;
6459                 }
6460                 result = winreg_set_printer_dataex(tmp_ctx, b,
6461                                           printer->sharename,
6462                                           SPOOL_DSSPOOLER_KEY,
6463                                           SPOOL_REG_PRINTERNAME,
6464                                           REG_SZ,
6465                                           buffer.data,
6466                                           buffer.length);
6467                 if (!W_ERROR_IS_OK(result)) {
6468                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6469                         goto done;
6470                 }
6471
6472                 if (!force_update) {
6473                         notify_printer_printername(server_event_context(),
6474                                                    msg_ctx, snum, p ? p : "");
6475                 }
6476         }
6477
6478         if (printer->portname != NULL &&
6479             (force_update ||
6480              !strequal(printer->portname, old_printer->portname))) {
6481                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6482                 if (!ok) {
6483                         DEBUG(0, ("portname data corrupted\n"));
6484                         result = WERR_INVALID_DATA;
6485                         goto done;
6486                 }
6487                 result = winreg_set_printer_dataex(tmp_ctx, b,
6488                                           printer->sharename,
6489                                           SPOOL_DSSPOOLER_KEY,
6490                                           SPOOL_REG_PORTNAME,
6491                                           REG_SZ,
6492                                           buffer.data,
6493                                           buffer.length);
6494                 if (!W_ERROR_IS_OK(result)) {
6495                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6496                         goto done;
6497                 }
6498
6499                 if (!force_update) {
6500                         notify_printer_port(server_event_context(),
6501                                             msg_ctx, snum, printer->portname ?
6502                                             printer->portname : "");
6503                 }
6504         }
6505
6506         if (printer->location != NULL &&
6507             (force_update ||
6508              !strequal(printer->location, old_printer->location))) {
6509                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6510                 if (!ok) {
6511                         DEBUG(0, ("location data corrupted\n"));
6512                         result = WERR_INVALID_DATA;
6513                         goto done;
6514                 }
6515                 result = winreg_set_printer_dataex(tmp_ctx, b,
6516                                           printer->sharename,
6517                                           SPOOL_DSSPOOLER_KEY,
6518                                           SPOOL_REG_LOCATION,
6519                                           REG_SZ,
6520                                           buffer.data,
6521                                           buffer.length);
6522                 if (!W_ERROR_IS_OK(result)) {
6523                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6524                         goto done;
6525                 }
6526
6527                 if (!force_update) {
6528                         notify_printer_location(server_event_context(),
6529                                                 msg_ctx, snum,
6530                                                 printer->location ?
6531                                                 printer->location : "");
6532                 }
6533         }
6534
6535         if (printer->sepfile != NULL &&
6536             (force_update ||
6537              !strequal(printer->sepfile, old_printer->sepfile))) {
6538                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6539                 if (!ok) {
6540                         DEBUG(0, ("sepfile data corrupted\n"));
6541                         result = WERR_INVALID_DATA;
6542                         goto done;
6543                 }
6544                 result = winreg_set_printer_dataex(tmp_ctx, b,
6545                                           printer->sharename,
6546                                           SPOOL_DSSPOOLER_KEY,
6547                                           SPOOL_REG_PRINTSEPARATORFILE,
6548                                           REG_SZ,
6549                                           buffer.data,
6550                                           buffer.length);
6551                 if (!W_ERROR_IS_OK(result)) {
6552                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6553                         goto done;
6554                 }
6555
6556                 if (!force_update) {
6557                         notify_printer_sepfile(server_event_context(),
6558                                                msg_ctx, snum,
6559                                                printer->sepfile ?
6560                                                printer->sepfile : "");
6561                 }
6562         }
6563
6564         if (printer->starttime != 0 &&
6565             (force_update ||
6566              printer->starttime != old_printer->starttime)) {
6567                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6568                 SIVAL(buffer.data, 0, printer->starttime);
6569                 result = winreg_set_printer_dataex(tmp_ctx, b,
6570                                           printer->sharename,
6571                                           SPOOL_DSSPOOLER_KEY,
6572                                           SPOOL_REG_PRINTSTARTTIME,
6573                                           REG_DWORD,
6574                                           buffer.data,
6575                                           buffer.length);
6576                 if (!W_ERROR_IS_OK(result)) {
6577                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6578                         goto done;
6579                 }
6580         }
6581
6582         if (printer->untiltime != 0 &&
6583             (force_update ||
6584              printer->untiltime != old_printer->untiltime)) {
6585                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6586                 SIVAL(buffer.data, 0, printer->untiltime);
6587                 result = winreg_set_printer_dataex(tmp_ctx, b,
6588                                           printer->sharename,
6589                                           SPOOL_DSSPOOLER_KEY,
6590                                           SPOOL_REG_PRINTENDTIME,
6591                                           REG_DWORD,
6592                                           buffer.data,
6593                                           buffer.length);
6594                 if (!W_ERROR_IS_OK(result)) {
6595                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6596                         goto done;
6597                 }
6598         }
6599
6600         if (force_update || printer->priority != old_printer->priority) {
6601                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6602                 SIVAL(buffer.data, 0, printer->priority);
6603                 result = winreg_set_printer_dataex(tmp_ctx, b,
6604                                           printer->sharename,
6605                                           SPOOL_DSSPOOLER_KEY,
6606                                           SPOOL_REG_PRIORITY,
6607                                           REG_DWORD,
6608                                           buffer.data,
6609                                           buffer.length);
6610                 if (!W_ERROR_IS_OK(result)) {
6611                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6612                         goto done;
6613                 }
6614         }
6615
6616         if (force_update || printer->attributes != old_printer->attributes) {
6617                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6618                 SIVAL(buffer.data, 0, (printer->attributes &
6619                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6620                 result = winreg_set_printer_dataex(tmp_ctx, b,
6621                                           printer->sharename,
6622                                           SPOOL_DSSPOOLER_KEY,
6623                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6624                                           REG_DWORD,
6625                                           buffer.data,
6626                                           buffer.length);
6627                 if (!W_ERROR_IS_OK(result)) {
6628                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6629                         goto done;
6630                 }
6631
6632                 switch (printer->attributes & 0x3) {
6633                         case 0:
6634                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6635                                 break;
6636                         case 1:
6637                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6638                                 break;
6639                         case 2:
6640                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6641                                 break;
6642                         default:
6643                                 spooling = "unknown";
6644                 }
6645                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6646                 if (!ok) {
6647                         DEBUG(0, ("printSpooling data corrupted\n"));
6648                         result = WERR_INVALID_DATA;
6649                         goto done;
6650                 }
6651                 winreg_set_printer_dataex(tmp_ctx, b,
6652                                           printer->sharename,
6653                                           SPOOL_DSSPOOLER_KEY,
6654                                           SPOOL_REG_PRINTSPOOLING,
6655                                           REG_SZ,
6656                                           buffer.data,
6657                                           buffer.length);
6658         }
6659
6660         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6661         if (!ok) {
6662                 DEBUG(0, ("shortServerName data corrupted\n"));
6663                 result = WERR_INVALID_DATA;
6664                 goto done;
6665         }
6666         result = winreg_set_printer_dataex(tmp_ctx, b,
6667                                   printer->sharename,
6668                                   SPOOL_DSSPOOLER_KEY,
6669                                   SPOOL_REG_SHORTSERVERNAME,
6670                                   REG_SZ,
6671                                   buffer.data,
6672                                   buffer.length);
6673         if (!W_ERROR_IS_OK(result)) {
6674                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6675                 goto done;
6676         }
6677
6678         dnsdomname = get_mydnsfullname();
6679         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6680                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6681         } else {
6682                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6683         }
6684         if (longname == NULL) {
6685                 result = WERR_NOMEM;
6686                 goto done;
6687         }
6688
6689         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6690         if (!ok) {
6691                 DEBUG(0, ("longname data corrupted\n"));
6692                 result = WERR_INVALID_DATA;
6693                 goto done;
6694         }
6695         result = winreg_set_printer_dataex(tmp_ctx, b,
6696                                            printer->sharename,
6697                                            SPOOL_DSSPOOLER_KEY,
6698                                            SPOOL_REG_SERVERNAME,
6699                                            REG_SZ,
6700                                            buffer.data,
6701                                            buffer.length);
6702         if (!W_ERROR_IS_OK(result)) {
6703                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6704                 goto done;
6705         }
6706
6707         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6708                                   lp_netbios_name(), printer->sharename);
6709         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6710         if (!ok) {
6711                 DEBUG(0, ("uncName data corrupted\n"));
6712                 result = WERR_INVALID_DATA;
6713                 goto done;
6714         }
6715         result = winreg_set_printer_dataex(tmp_ctx, b,
6716                                   printer->sharename,
6717                                   SPOOL_DSSPOOLER_KEY,
6718                                   SPOOL_REG_UNCNAME,
6719                                   REG_SZ,
6720                                   buffer.data,
6721                                   buffer.length);
6722         if (!W_ERROR_IS_OK(result)) {
6723                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6724                 goto done;
6725         }
6726
6727 done:
6728         talloc_free(tmp_ctx);
6729         return result;
6730 }
6731
6732 /********************************************************************
6733  * Called by spoolss_api_setprinter
6734  * when updating a printer description.
6735  ********************************************************************/
6736
6737 static WERROR update_printer(struct pipes_struct *p,
6738                              struct policy_handle *handle,
6739                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6740                              struct spoolss_DeviceMode *devmode)
6741 {
6742         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6743         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6744         struct spoolss_PrinterInfo2 *old_printer;
6745         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6746         int snum;
6747         WERROR result = WERR_OK;
6748         TALLOC_CTX *tmp_ctx;
6749         struct dcerpc_binding_handle *b;
6750
6751         DEBUG(8,("update_printer\n"));
6752
6753         tmp_ctx = talloc_new(p->mem_ctx);
6754         if (tmp_ctx == NULL) {
6755                 return WERR_NOMEM;
6756         }
6757
6758         if (!Printer) {
6759                 result = WERR_BADFID;
6760                 goto done;
6761         }
6762
6763         if (!get_printer_snum(p, handle, &snum, NULL)) {
6764                 result = WERR_BADFID;
6765                 goto done;
6766         }
6767
6768         result = winreg_printer_binding_handle(tmp_ctx,
6769                                                get_session_info_system(),
6770                                                p->msg_ctx,
6771                                                &b);
6772         if (!W_ERROR_IS_OK(result)) {
6773                 goto done;
6774         }
6775
6776         result = winreg_get_printer(tmp_ctx, b,
6777                                     lp_const_servicename(snum),
6778                                     &old_printer);
6779         if (!W_ERROR_IS_OK(result)) {
6780                 result = WERR_BADFID;
6781                 goto done;
6782         }
6783
6784         /* Do sanity check on the requested changes for Samba */
6785         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6786                 result = WERR_INVALID_PARAM;
6787                 goto done;
6788         }
6789
6790         /* FIXME!!! If the driver has changed we really should verify that
6791            it is installed before doing much else   --jerry */
6792
6793         /* Check calling user has permission to update printer description */
6794         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6795                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6796                 result = WERR_ACCESS_DENIED;
6797                 goto done;
6798         }
6799
6800         /* Call addprinter hook */
6801         /* Check changes to see if this is really needed */
6802
6803         if (*lp_addprinter_command(talloc_tos()) &&
6804                         (!strequal(printer->drivername, old_printer->drivername) ||
6805                          !strequal(printer->comment, old_printer->comment) ||
6806                          !strequal(printer->portname, old_printer->portname) ||
6807                          !strequal(printer->location, old_printer->location)) )
6808         {
6809                 char *raddr;
6810
6811                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6812                                                          p->mem_ctx);
6813                 if (raddr == NULL) {
6814                         return WERR_NOMEM;
6815                 }
6816
6817                 /* add_printer_hook() will call reload_services() */
6818                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6819                                       printer, raddr,
6820                                       p->msg_ctx)) {
6821                         result = WERR_ACCESS_DENIED;
6822                         goto done;
6823                 }
6824         }
6825
6826         result = update_dsspooler(tmp_ctx,
6827                                   get_session_info_system(),
6828                                   p->msg_ctx,
6829                                   snum,
6830                                   printer,
6831                                   old_printer);
6832         if (!W_ERROR_IS_OK(result)) {
6833                 goto done;
6834         }
6835
6836         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6837
6838         if (devmode == NULL) {
6839                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6840         }
6841         result = winreg_update_printer(tmp_ctx, b,
6842                                        printer->sharename,
6843                                        printer_mask,
6844                                        printer,
6845                                        devmode,
6846                                        NULL);
6847
6848 done:
6849         talloc_free(tmp_ctx);
6850
6851         return result;
6852 }
6853
6854 /****************************************************************************
6855 ****************************************************************************/
6856 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6857                                            struct policy_handle *handle,
6858                                            struct spoolss_SetPrinterInfo7 *info7)
6859 {
6860 #ifdef HAVE_ADS
6861         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6862         WERROR result;
6863         int snum;
6864         struct printer_handle *Printer;
6865
6866         if ( lp_security() != SEC_ADS ) {
6867                 return WERR_UNKNOWN_LEVEL;
6868         }
6869
6870         Printer = find_printer_index_by_hnd(p, handle);
6871
6872         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6873
6874         if (!Printer)
6875                 return WERR_BADFID;
6876
6877         if (!get_printer_snum(p, handle, &snum, NULL))
6878                 return WERR_BADFID;
6879
6880         result = winreg_get_printer_internal(p->mem_ctx,
6881                                     get_session_info_system(),
6882                                     p->msg_ctx,
6883                                     lp_servicename(talloc_tos(), snum),
6884                                     &pinfo2);
6885         if (!W_ERROR_IS_OK(result)) {
6886                 return WERR_BADFID;
6887         }
6888
6889         nt_printer_publish(pinfo2,
6890                            get_session_info_system(),
6891                            p->msg_ctx,
6892                            pinfo2,
6893                            info7->action);
6894
6895         TALLOC_FREE(pinfo2);
6896         return WERR_OK;
6897 #else
6898         return WERR_UNKNOWN_LEVEL;
6899 #endif
6900 }
6901
6902 /********************************************************************
6903  ********************************************************************/
6904
6905 static WERROR update_printer_devmode(struct pipes_struct *p,
6906                                      struct policy_handle *handle,
6907                                      struct spoolss_DeviceMode *devmode)
6908 {
6909         int snum;
6910         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6911         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6912
6913         DEBUG(8,("update_printer_devmode\n"));
6914
6915         if (!Printer) {
6916                 return WERR_BADFID;
6917         }
6918
6919         if (!get_printer_snum(p, handle, &snum, NULL)) {
6920                 return WERR_BADFID;
6921         }
6922
6923         /* Check calling user has permission to update printer description */
6924         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6925                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6926                 return WERR_ACCESS_DENIED;
6927         }
6928
6929         return winreg_update_printer_internal(p->mem_ctx,
6930                                      get_session_info_system(),
6931                                      p->msg_ctx,
6932                                      lp_const_servicename(snum),
6933                                      info2_mask,
6934                                      NULL,
6935                                      devmode,
6936                                      NULL);
6937 }
6938
6939
6940 /****************************************************************
6941  _spoolss_SetPrinter
6942 ****************************************************************/
6943
6944 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6945                            struct spoolss_SetPrinter *r)
6946 {
6947         WERROR result;
6948
6949         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6950
6951         if (!Printer) {
6952                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6953                         OUR_HANDLE(r->in.handle)));
6954                 return WERR_BADFID;
6955         }
6956
6957         /* check the level */
6958         switch (r->in.info_ctr->level) {
6959                 case 0:
6960                         return control_printer(r->in.handle, r->in.command, p);
6961                 case 2:
6962                         result = update_printer(p, r->in.handle,
6963                                                 r->in.info_ctr,
6964                                                 r->in.devmode_ctr->devmode);
6965                         if (!W_ERROR_IS_OK(result))
6966                                 return result;
6967                         if (r->in.secdesc_ctr->sd)
6968                                 result = update_printer_sec(r->in.handle, p,
6969                                                             r->in.secdesc_ctr);
6970                         return result;
6971                 case 3:
6972                         return update_printer_sec(r->in.handle, p,
6973                                                   r->in.secdesc_ctr);
6974                 case 7:
6975                         return publish_or_unpublish_printer(p, r->in.handle,
6976                                                             r->in.info_ctr->info.info7);
6977                 case 8:
6978                         return update_printer_devmode(p, r->in.handle,
6979                                                       r->in.devmode_ctr->devmode);
6980                 default:
6981                         return WERR_UNKNOWN_LEVEL;
6982         }
6983 }
6984
6985 /****************************************************************
6986  _spoolss_FindClosePrinterNotify
6987 ****************************************************************/
6988
6989 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6990                                        struct spoolss_FindClosePrinterNotify *r)
6991 {
6992         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6993
6994         if (!Printer) {
6995                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6996                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6997                 return WERR_BADFID;
6998         }
6999
7000         if (Printer->notify.cli_chan != NULL &&
7001             Printer->notify.cli_chan->active_connections > 0) {
7002                 int snum = -1;
7003
7004                 if (Printer->printer_type == SPLHND_PRINTER) {
7005                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7006                                 return WERR_BADFID;
7007                         }
7008                 }
7009
7010                 srv_spoolss_replycloseprinter(snum, Printer);
7011         }
7012
7013         Printer->notify.flags=0;
7014         Printer->notify.options=0;
7015         Printer->notify.localmachine[0]='\0';
7016         Printer->notify.printerlocal=0;
7017         TALLOC_FREE(Printer->notify.option);
7018
7019         return WERR_OK;
7020 }
7021
7022 /****************************************************************
7023  _spoolss_AddJob
7024 ****************************************************************/
7025
7026 WERROR _spoolss_AddJob(struct pipes_struct *p,
7027                        struct spoolss_AddJob *r)
7028 {
7029         if (!r->in.buffer && (r->in.offered != 0)) {
7030                 return WERR_INVALID_PARAM;
7031         }
7032
7033         /* this is what a NT server returns for AddJob. AddJob must fail on
7034          * non-local printers */
7035
7036         if (r->in.level != 1) {
7037                 return WERR_UNKNOWN_LEVEL;
7038         }
7039
7040         return WERR_INVALID_PARAM;
7041 }
7042
7043 /****************************************************************************
7044 fill_job_info1
7045 ****************************************************************************/
7046
7047 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7048                              struct spoolss_JobInfo1 *r,
7049                              const print_queue_struct *queue,
7050                              int position, int snum,
7051                              struct spoolss_PrinterInfo2 *pinfo2)
7052 {
7053         struct tm *t;
7054
7055         t = gmtime(&queue->time);
7056
7057         r->job_id               = queue->sysjob;
7058
7059         r->printer_name         = lp_servicename(mem_ctx, snum);
7060         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7061         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7062         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7063         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7064         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7065         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7066         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7067         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7068         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7069         r->text_status          = talloc_strdup(mem_ctx, "");
7070         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7071
7072         r->status               = nt_printj_status(queue->status);
7073         r->priority             = queue->priority;
7074         r->position             = position;
7075         r->total_pages          = queue->page_count;
7076         r->pages_printed        = 0; /* ??? */
7077
7078         init_systemtime(&r->submitted, t);
7079
7080         return WERR_OK;
7081 }
7082
7083 /****************************************************************************
7084 fill_job_info2
7085 ****************************************************************************/
7086
7087 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7088                              struct spoolss_JobInfo2 *r,
7089                              const print_queue_struct *queue,
7090                              int position, int snum,
7091                              struct spoolss_PrinterInfo2 *pinfo2,
7092                              struct spoolss_DeviceMode *devmode)
7093 {
7094         struct tm *t;
7095
7096         t = gmtime(&queue->time);
7097
7098         r->job_id               = queue->sysjob;
7099
7100         r->printer_name         = lp_servicename(mem_ctx, snum);
7101         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7102         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7103         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7104         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7105         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7106         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7107         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7108         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7109         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7110         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7111         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7112         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7113         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7114         r->parameters           = talloc_strdup(mem_ctx, "");
7115         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7116         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7117         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7118
7119         r->devmode              = devmode;
7120
7121         r->text_status          = talloc_strdup(mem_ctx, "");
7122         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7123
7124         r->secdesc              = NULL;
7125
7126         r->status               = nt_printj_status(queue->status);
7127         r->priority             = queue->priority;
7128         r->position             = position;
7129         r->start_time           = 0;
7130         r->until_time           = 0;
7131         r->total_pages          = queue->page_count;
7132         r->size                 = queue->size;
7133         init_systemtime(&r->submitted, t);
7134         r->time                 = 0;
7135         r->pages_printed        = 0; /* ??? */
7136
7137         return WERR_OK;
7138 }
7139
7140 /****************************************************************************
7141 fill_job_info3
7142 ****************************************************************************/
7143
7144 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7145                              struct spoolss_JobInfo3 *r,
7146                              const print_queue_struct *queue,
7147                              const print_queue_struct *next_queue,
7148                              int position, int snum,
7149                              struct spoolss_PrinterInfo2 *pinfo2)
7150 {
7151         r->job_id               = queue->sysjob;
7152         r->next_job_id          = 0;
7153         if (next_queue) {
7154                 r->next_job_id  = next_queue->sysjob;
7155         }
7156         r->reserved             = 0;
7157
7158         return WERR_OK;
7159 }
7160
7161 /****************************************************************************
7162  Enumjobs at level 1.
7163 ****************************************************************************/
7164
7165 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7166                               const print_queue_struct *queue,
7167                               uint32_t num_queues, int snum,
7168                               struct spoolss_PrinterInfo2 *pinfo2,
7169                               union spoolss_JobInfo **info_p,
7170                               uint32_t *count)
7171 {
7172         union spoolss_JobInfo *info;
7173         int i;
7174         WERROR result = WERR_OK;
7175
7176         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7177         W_ERROR_HAVE_NO_MEMORY(info);
7178
7179         *count = num_queues;
7180
7181         for (i=0; i<*count; i++) {
7182                 result = fill_job_info1(info,
7183                                         &info[i].info1,
7184                                         &queue[i],
7185                                         i,
7186                                         snum,
7187                                         pinfo2);
7188                 if (!W_ERROR_IS_OK(result)) {
7189                         goto out;
7190                 }
7191         }
7192
7193  out:
7194         if (!W_ERROR_IS_OK(result)) {
7195                 TALLOC_FREE(info);
7196                 *count = 0;
7197                 return result;
7198         }
7199
7200         *info_p = info;
7201
7202         return WERR_OK;
7203 }
7204
7205 /****************************************************************************
7206  Enumjobs at level 2.
7207 ****************************************************************************/
7208
7209 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7210                               const print_queue_struct *queue,
7211                               uint32_t num_queues, int snum,
7212                               struct spoolss_PrinterInfo2 *pinfo2,
7213                               union spoolss_JobInfo **info_p,
7214                               uint32_t *count)
7215 {
7216         union spoolss_JobInfo *info;
7217         int i;
7218         WERROR result = WERR_OK;
7219
7220         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7221         W_ERROR_HAVE_NO_MEMORY(info);
7222
7223         *count = num_queues;
7224
7225         for (i=0; i<*count; i++) {
7226                 struct spoolss_DeviceMode *devmode;
7227
7228                 result = spoolss_create_default_devmode(info,
7229                                                         pinfo2->printername,
7230                                                         &devmode);
7231                 if (!W_ERROR_IS_OK(result)) {
7232                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7233                         goto out;
7234                 }
7235
7236                 result = fill_job_info2(info,
7237                                         &info[i].info2,
7238                                         &queue[i],
7239                                         i,
7240                                         snum,
7241                                         pinfo2,
7242                                         devmode);
7243                 if (!W_ERROR_IS_OK(result)) {
7244                         goto out;
7245                 }
7246         }
7247
7248  out:
7249         if (!W_ERROR_IS_OK(result)) {
7250                 TALLOC_FREE(info);
7251                 *count = 0;
7252                 return result;
7253         }
7254
7255         *info_p = info;
7256
7257         return WERR_OK;
7258 }
7259
7260 /****************************************************************************
7261  Enumjobs at level 3.
7262 ****************************************************************************/
7263
7264 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7265                               const print_queue_struct *queue,
7266                               uint32_t num_queues, int snum,
7267                               struct spoolss_PrinterInfo2 *pinfo2,
7268                               union spoolss_JobInfo **info_p,
7269                               uint32_t *count)
7270 {
7271         union spoolss_JobInfo *info;
7272         int i;
7273         WERROR result = WERR_OK;
7274
7275         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7276         W_ERROR_HAVE_NO_MEMORY(info);
7277
7278         *count = num_queues;
7279
7280         for (i=0; i<*count; i++) {
7281                 const print_queue_struct *next_queue = NULL;
7282
7283                 if (i+1 < *count) {
7284                         next_queue = &queue[i+1];
7285                 }
7286
7287                 result = fill_job_info3(info,
7288                                         &info[i].info3,
7289                                         &queue[i],
7290                                         next_queue,
7291                                         i,
7292                                         snum,
7293                                         pinfo2);
7294                 if (!W_ERROR_IS_OK(result)) {
7295                         goto out;
7296                 }
7297         }
7298
7299  out:
7300         if (!W_ERROR_IS_OK(result)) {
7301                 TALLOC_FREE(info);
7302                 *count = 0;
7303                 return result;
7304         }
7305
7306         *info_p = info;
7307
7308         return WERR_OK;
7309 }
7310
7311 /****************************************************************
7312  _spoolss_EnumJobs
7313 ****************************************************************/
7314
7315 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7316                          struct spoolss_EnumJobs *r)
7317 {
7318         WERROR result;
7319         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7320         int snum;
7321         print_status_struct prt_status;
7322         print_queue_struct *queue = NULL;
7323         uint32_t count;
7324
7325         /* that's an [in out] buffer */
7326
7327         if (!r->in.buffer && (r->in.offered != 0)) {
7328                 return WERR_INVALID_PARAM;
7329         }
7330
7331         DEBUG(4,("_spoolss_EnumJobs\n"));
7332
7333         *r->out.needed = 0;
7334         *r->out.count = 0;
7335         *r->out.info = NULL;
7336
7337         /* lookup the printer snum and tdb entry */
7338
7339         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7340                 return WERR_BADFID;
7341         }
7342
7343         result = winreg_get_printer_internal(p->mem_ctx,
7344                                     get_session_info_system(),
7345                                     p->msg_ctx,
7346                                     lp_const_servicename(snum),
7347                                     &pinfo2);
7348         if (!W_ERROR_IS_OK(result)) {
7349                 return result;
7350         }
7351
7352         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7353         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7354                 count, prt_status.status, prt_status.message));
7355
7356         if (count == 0) {
7357                 SAFE_FREE(queue);
7358                 TALLOC_FREE(pinfo2);
7359                 return WERR_OK;
7360         }
7361
7362         switch (r->in.level) {
7363         case 1:
7364                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7365                                          pinfo2, r->out.info, r->out.count);
7366                 break;
7367         case 2:
7368                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7369                                          pinfo2, r->out.info, r->out.count);
7370                 break;
7371         case 3:
7372                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7373                                          pinfo2, r->out.info, r->out.count);
7374                 break;
7375         default:
7376                 result = WERR_UNKNOWN_LEVEL;
7377                 break;
7378         }
7379
7380         SAFE_FREE(queue);
7381         TALLOC_FREE(pinfo2);
7382
7383         if (!W_ERROR_IS_OK(result)) {
7384                 return result;
7385         }
7386
7387         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7388                                                      spoolss_EnumJobs,
7389                                                      *r->out.info, r->in.level,
7390                                                      *r->out.count);
7391         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7392         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7393
7394         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7395 }
7396
7397 /****************************************************************
7398  _spoolss_ScheduleJob
7399 ****************************************************************/
7400
7401 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7402                             struct spoolss_ScheduleJob *r)
7403 {
7404         return WERR_OK;
7405 }
7406
7407 /****************************************************************
7408 ****************************************************************/
7409
7410 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7411                                struct messaging_context *msg_ctx,
7412                                const char *printer_name,
7413                                uint32_t job_id,
7414                                struct spoolss_SetJobInfo1 *r)
7415 {
7416         char *old_doc_name;
7417
7418         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7419                 return WERR_BADFID;
7420         }
7421
7422         if (strequal(old_doc_name, r->document_name)) {
7423                 return WERR_OK;
7424         }
7425
7426         if (!print_job_set_name(server_event_context(), msg_ctx,
7427                                 printer_name, job_id, r->document_name)) {
7428                 return WERR_BADFID;
7429         }
7430
7431         return WERR_OK;
7432 }
7433
7434 /****************************************************************
7435  _spoolss_SetJob
7436 ****************************************************************/
7437
7438 WERROR _spoolss_SetJob(struct pipes_struct *p,
7439                        struct spoolss_SetJob *r)
7440 {
7441         const struct auth_session_info *session_info = p->session_info;
7442         int snum;
7443         WERROR errcode = WERR_BADFUNC;
7444
7445         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7446                 return WERR_BADFID;
7447         }
7448
7449         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7450                 return WERR_INVALID_PRINTER_NAME;
7451         }
7452
7453         switch (r->in.command) {
7454         case SPOOLSS_JOB_CONTROL_CANCEL:
7455         case SPOOLSS_JOB_CONTROL_DELETE:
7456                 errcode = print_job_delete(session_info, p->msg_ctx,
7457                                            snum, r->in.job_id);
7458                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7459                         errcode = WERR_OK;
7460                 }
7461                 break;
7462         case SPOOLSS_JOB_CONTROL_PAUSE:
7463                 errcode = print_job_pause(session_info, p->msg_ctx,
7464                                           snum, r->in.job_id);
7465                 break;
7466         case SPOOLSS_JOB_CONTROL_RESTART:
7467         case SPOOLSS_JOB_CONTROL_RESUME:
7468                 errcode = print_job_resume(session_info, p->msg_ctx,
7469                                            snum, r->in.job_id);
7470                 break;
7471         case 0:
7472                 errcode = WERR_OK;
7473                 break;
7474         default:
7475                 return WERR_UNKNOWN_LEVEL;
7476         }
7477
7478         if (!W_ERROR_IS_OK(errcode)) {
7479                 return errcode;
7480         }
7481
7482         if (r->in.ctr == NULL) {
7483                 return errcode;
7484         }
7485
7486         switch (r->in.ctr->level) {
7487         case 1:
7488                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7489                                            lp_const_servicename(snum),
7490                                            r->in.job_id,
7491                                            r->in.ctr->info.info1);
7492                 break;
7493         case 2:
7494         case 3:
7495         case 4:
7496         default:
7497                 return WERR_UNKNOWN_LEVEL;
7498         }
7499
7500         return errcode;
7501 }
7502
7503 /****************************************************************************
7504  Enumerates all printer drivers by level and architecture.
7505 ****************************************************************************/
7506
7507 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7508                                                        const struct auth_session_info *session_info,
7509                                                        struct messaging_context *msg_ctx,
7510                                                        const char *servername,
7511                                                        const char *architecture,
7512                                                        uint32_t level,
7513                                                        union spoolss_DriverInfo **info_p,
7514                                                        uint32_t *count_p)
7515 {
7516         int i;
7517         uint32_t version;
7518         struct spoolss_DriverInfo8 *driver;
7519         union spoolss_DriverInfo *info = NULL;
7520         uint32_t count = 0;
7521         WERROR result = WERR_OK;
7522         uint32_t num_drivers;
7523         const char **drivers;
7524         struct dcerpc_binding_handle *b;
7525         TALLOC_CTX *tmp_ctx = NULL;
7526
7527         *count_p = 0;
7528         *info_p = NULL;
7529
7530         tmp_ctx = talloc_new(mem_ctx);
7531         if (!tmp_ctx) {
7532                 return WERR_NOMEM;
7533         }
7534
7535         result = winreg_printer_binding_handle(tmp_ctx,
7536                                                session_info,
7537                                                msg_ctx,
7538                                                &b);
7539         if (!W_ERROR_IS_OK(result)) {
7540                 goto out;
7541         }
7542
7543         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7544                 result = winreg_get_driver_list(tmp_ctx, b,
7545                                                 architecture, version,
7546                                                 &num_drivers, &drivers);
7547                 if (!W_ERROR_IS_OK(result)) {
7548                         goto out;
7549                 }
7550                 DEBUG(4, ("we have:[%d] drivers in environment"
7551                           " [%s] and version [%d]\n",
7552                           num_drivers, architecture, version));
7553
7554                 if (num_drivers != 0) {
7555                         info = talloc_realloc(tmp_ctx, info,
7556                                                     union spoolss_DriverInfo,
7557                                                     count + num_drivers);
7558                         if (!info) {
7559                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7560                                         "failed to enlarge driver info buffer!\n"));
7561                                 result = WERR_NOMEM;
7562                                 goto out;
7563                         }
7564                 }
7565
7566                 for (i = 0; i < num_drivers; i++) {
7567                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7568
7569                         result = winreg_get_driver(tmp_ctx, b,
7570                                                    architecture, drivers[i],
7571                                                    version, &driver);
7572                         if (!W_ERROR_IS_OK(result)) {
7573                                 goto out;
7574                         }
7575
7576                         switch (level) {
7577                         case 1:
7578                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7579                                                                    driver, servername);
7580                                 break;
7581                         case 2:
7582                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7583                                                                    driver, servername);
7584                                 break;
7585                         case 3:
7586                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7587                                                                    driver, servername);
7588                                 break;
7589                         case 4:
7590                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7591                                                                    driver, servername);
7592                                 break;
7593                         case 5:
7594                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7595                                                                    driver, servername);
7596                                 break;
7597                         case 6:
7598                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7599                                                                    driver, servername);
7600                                 break;
7601                         case 8:
7602                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7603                                                                    driver, servername);
7604                                 break;
7605                         default:
7606                                 result = WERR_UNKNOWN_LEVEL;
7607                                 break;
7608                         }
7609
7610                         TALLOC_FREE(driver);
7611
7612                         if (!W_ERROR_IS_OK(result)) {
7613                                 goto out;
7614                         }
7615                 }
7616
7617                 count += num_drivers;
7618                 TALLOC_FREE(drivers);
7619         }
7620
7621 out:
7622         if (W_ERROR_IS_OK(result)) {
7623                 *info_p = talloc_move(mem_ctx, &info);
7624                 *count_p = count;
7625         }
7626
7627         talloc_free(tmp_ctx);
7628         return result;
7629 }
7630
7631 /****************************************************************************
7632  Enumerates all printer drivers by level.
7633 ****************************************************************************/
7634
7635 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7636                                        const struct auth_session_info *session_info,
7637                                        struct messaging_context *msg_ctx,
7638                                        const char *servername,
7639                                        const char *architecture,
7640                                        uint32_t level,
7641                                        union spoolss_DriverInfo **info_p,
7642                                        uint32_t *count_p)
7643 {
7644         uint32_t a,i;
7645         WERROR result = WERR_OK;
7646
7647         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7648
7649                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7650
7651                         union spoolss_DriverInfo *info = NULL;
7652                         uint32_t count = 0;
7653
7654                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7655                                                                           session_info,
7656                                                                           msg_ctx,
7657                                                                           servername,
7658                                                                           archi_table[a].long_archi,
7659                                                                           level,
7660                                                                           &info,
7661                                                                           &count);
7662                         if (!W_ERROR_IS_OK(result)) {
7663                                 continue;
7664                         }
7665
7666                         for (i=0; i < count; i++) {
7667                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7668                                              info[i], info_p, count_p);
7669                         }
7670                 }
7671
7672                 return result;
7673         }
7674
7675         return enumprinterdrivers_level_by_architecture(mem_ctx,
7676                                                         session_info,
7677                                                         msg_ctx,
7678                                                         servername,
7679                                                         architecture,
7680                                                         level,
7681                                                         info_p,
7682                                                         count_p);
7683 }
7684
7685 /****************************************************************
7686  _spoolss_EnumPrinterDrivers
7687 ****************************************************************/
7688
7689 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7690                                    struct spoolss_EnumPrinterDrivers *r)
7691 {
7692         const char *cservername;
7693         WERROR result;
7694
7695         /* that's an [in out] buffer */
7696
7697         if (!r->in.buffer && (r->in.offered != 0)) {
7698                 return WERR_INVALID_PARAM;
7699         }
7700
7701         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7702
7703         *r->out.needed = 0;
7704         *r->out.count = 0;
7705         *r->out.info = NULL;
7706
7707         cservername = canon_servername(r->in.server);
7708
7709         if (!is_myname_or_ipaddr(cservername)) {
7710                 return WERR_UNKNOWN_PRINTER_DRIVER;
7711         }
7712
7713         result = enumprinterdrivers_level(p->mem_ctx,
7714                                           get_session_info_system(),
7715                                           p->msg_ctx,
7716                                           cservername,
7717                                           r->in.environment,
7718                                           r->in.level,
7719                                           r->out.info,
7720                                           r->out.count);
7721         if (!W_ERROR_IS_OK(result)) {
7722                 return result;
7723         }
7724
7725         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7726                                                      spoolss_EnumPrinterDrivers,
7727                                                      *r->out.info, r->in.level,
7728                                                      *r->out.count);
7729         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7730         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7731
7732         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7733 }
7734
7735 /****************************************************************
7736  _spoolss_EnumForms
7737 ****************************************************************/
7738
7739 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7740                           struct spoolss_EnumForms *r)
7741 {
7742         WERROR result;
7743
7744         *r->out.count = 0;
7745         *r->out.needed = 0;
7746         *r->out.info = NULL;
7747
7748         /* that's an [in out] buffer */
7749
7750         if (!r->in.buffer && (r->in.offered != 0) ) {
7751                 return WERR_INVALID_PARAM;
7752         }
7753
7754         DEBUG(4,("_spoolss_EnumForms\n"));
7755         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7756         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7757
7758         switch (r->in.level) {
7759         case 1:
7760                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7761                                                    get_session_info_system(),
7762                                                    p->msg_ctx,
7763                                                    r->out.count,
7764                                                    r->out.info);
7765                 break;
7766         default:
7767                 result = WERR_UNKNOWN_LEVEL;
7768                 break;
7769         }
7770
7771         if (!W_ERROR_IS_OK(result)) {
7772                 return result;
7773         }
7774
7775         if (*r->out.count == 0) {
7776                 return WERR_NO_MORE_ITEMS;
7777         }
7778
7779         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7780                                                      spoolss_EnumForms,
7781                                                      *r->out.info, r->in.level,
7782                                                      *r->out.count);
7783         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7784         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7785
7786         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7787 }
7788
7789 /****************************************************************
7790  _spoolss_GetForm
7791 ****************************************************************/
7792
7793 WERROR _spoolss_GetForm(struct pipes_struct *p,
7794                         struct spoolss_GetForm *r)
7795 {
7796         WERROR result;
7797
7798         /* that's an [in out] buffer */
7799
7800         if (!r->in.buffer && (r->in.offered != 0)) {
7801                 return WERR_INVALID_PARAM;
7802         }
7803
7804         DEBUG(4,("_spoolss_GetForm\n"));
7805         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7806         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7807
7808         switch (r->in.level) {
7809         case 1:
7810                 result = winreg_printer_getform1_internal(p->mem_ctx,
7811                                                  get_session_info_system(),
7812                                                  p->msg_ctx,
7813                                                  r->in.form_name,
7814                                                  &r->out.info->info1);
7815                 break;
7816         default:
7817                 result = WERR_UNKNOWN_LEVEL;
7818                 break;
7819         }
7820
7821         if (!W_ERROR_IS_OK(result)) {
7822                 TALLOC_FREE(r->out.info);
7823                 return result;
7824         }
7825
7826         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7827                                                r->out.info, r->in.level);
7828         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7829
7830         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7831 }
7832
7833 /****************************************************************************
7834 ****************************************************************************/
7835
7836 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7837                           struct spoolss_PortInfo1 *r,
7838                           const char *name)
7839 {
7840         r->port_name = talloc_strdup(mem_ctx, name);
7841         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7842
7843         return WERR_OK;
7844 }
7845
7846 /****************************************************************************
7847  TODO: This probably needs distinguish between TCP/IP and Local ports
7848  somehow.
7849 ****************************************************************************/
7850
7851 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7852                           struct spoolss_PortInfo2 *r,
7853                           const char *name)
7854 {
7855         r->port_name = talloc_strdup(mem_ctx, name);
7856         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7857
7858         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7859         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7860
7861         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7862         W_ERROR_HAVE_NO_MEMORY(r->description);
7863
7864         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7865         r->reserved = 0;
7866
7867         return WERR_OK;
7868 }
7869
7870
7871 /****************************************************************************
7872  wrapper around the enumer ports command
7873 ****************************************************************************/
7874
7875 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7876 {
7877         char *cmd = lp_enumports_command(talloc_tos());
7878         char **qlines = NULL;
7879         char *command = NULL;
7880         int numlines;
7881         int ret;
7882         int fd;
7883
7884         *count = 0;
7885         *lines = NULL;
7886
7887         /* if no hook then just fill in the default port */
7888
7889         if ( !*cmd ) {
7890                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7891                         return WERR_NOMEM;
7892                 }
7893                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7894                         TALLOC_FREE(qlines);
7895                         return WERR_NOMEM;
7896                 }
7897                 qlines[1] = NULL;
7898                 numlines = 1;
7899         }
7900         else {
7901                 /* we have a valid enumport command */
7902
7903                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7904                 if (!command) {
7905                         return WERR_NOMEM;
7906                 }
7907
7908                 DEBUG(10,("Running [%s]\n", command));
7909                 ret = smbrun(command, &fd);
7910                 DEBUG(10,("Returned [%d]\n", ret));
7911                 TALLOC_FREE(command);
7912                 if (ret != 0) {
7913                         if (fd != -1) {
7914                                 close(fd);
7915                         }
7916                         return WERR_ACCESS_DENIED;
7917                 }
7918
7919                 numlines = 0;
7920                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7921                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7922                 close(fd);
7923         }
7924
7925         *count = numlines;
7926         *lines = qlines;
7927
7928         return WERR_OK;
7929 }
7930
7931 /****************************************************************************
7932  enumports level 1.
7933 ****************************************************************************/
7934
7935 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7936                                 union spoolss_PortInfo **info_p,
7937                                 uint32_t *count)
7938 {
7939         union spoolss_PortInfo *info = NULL;
7940         int i=0;
7941         WERROR result = WERR_OK;
7942         char **qlines = NULL;
7943         int numlines = 0;
7944
7945         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7946         if (!W_ERROR_IS_OK(result)) {
7947                 goto out;
7948         }
7949
7950         if (numlines) {
7951                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7952                 if (!info) {
7953                         DEBUG(10,("Returning WERR_NOMEM\n"));
7954                         result = WERR_NOMEM;
7955                         goto out;
7956                 }
7957
7958                 for (i=0; i<numlines; i++) {
7959                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7960                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7961                         if (!W_ERROR_IS_OK(result)) {
7962                                 goto out;
7963                         }
7964                 }
7965         }
7966         TALLOC_FREE(qlines);
7967
7968 out:
7969         if (!W_ERROR_IS_OK(result)) {
7970                 TALLOC_FREE(info);
7971                 TALLOC_FREE(qlines);
7972                 *count = 0;
7973                 *info_p = NULL;
7974                 return result;
7975         }
7976
7977         *info_p = info;
7978         *count = numlines;
7979
7980         return WERR_OK;
7981 }
7982
7983 /****************************************************************************
7984  enumports level 2.
7985 ****************************************************************************/
7986
7987 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7988                                 union spoolss_PortInfo **info_p,
7989                                 uint32_t *count)
7990 {
7991         union spoolss_PortInfo *info = NULL;
7992         int i=0;
7993         WERROR result = WERR_OK;
7994         char **qlines = NULL;
7995         int numlines = 0;
7996
7997         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7998         if (!W_ERROR_IS_OK(result)) {
7999                 goto out;
8000         }
8001
8002         if (numlines) {
8003                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8004                 if (!info) {
8005                         DEBUG(10,("Returning WERR_NOMEM\n"));
8006                         result = WERR_NOMEM;
8007                         goto out;
8008                 }
8009
8010                 for (i=0; i<numlines; i++) {
8011                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8012                         result = fill_port_2(info, &info[i].info2, qlines[i]);
8013                         if (!W_ERROR_IS_OK(result)) {
8014                                 goto out;
8015                         }
8016                 }
8017         }
8018         TALLOC_FREE(qlines);
8019
8020 out:
8021         if (!W_ERROR_IS_OK(result)) {
8022                 TALLOC_FREE(info);
8023                 TALLOC_FREE(qlines);
8024                 *count = 0;
8025                 *info_p = NULL;
8026                 return result;
8027         }
8028
8029         *info_p = info;
8030         *count = numlines;
8031
8032         return WERR_OK;
8033 }
8034
8035 /****************************************************************
8036  _spoolss_EnumPorts
8037 ****************************************************************/
8038
8039 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8040                           struct spoolss_EnumPorts *r)
8041 {
8042         WERROR result;
8043
8044         /* that's an [in out] buffer */
8045
8046         if (!r->in.buffer && (r->in.offered != 0)) {
8047                 return WERR_INVALID_PARAM;
8048         }
8049
8050         DEBUG(4,("_spoolss_EnumPorts\n"));
8051
8052         *r->out.count = 0;
8053         *r->out.needed = 0;
8054         *r->out.info = NULL;
8055
8056         switch (r->in.level) {
8057         case 1:
8058                 result = enumports_level_1(p->mem_ctx, r->out.info,
8059                                            r->out.count);
8060                 break;
8061         case 2:
8062                 result = enumports_level_2(p->mem_ctx, r->out.info,
8063                                            r->out.count);
8064                 break;
8065         default:
8066                 return WERR_UNKNOWN_LEVEL;
8067         }
8068
8069         if (!W_ERROR_IS_OK(result)) {
8070                 return result;
8071         }
8072
8073         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8074                                                      spoolss_EnumPorts,
8075                                                      *r->out.info, r->in.level,
8076                                                      *r->out.count);
8077         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8078         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8079
8080         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8081 }
8082
8083 /****************************************************************************
8084 ****************************************************************************/
8085
8086 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8087                                            const char *server,
8088                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8089                                            struct spoolss_DeviceMode *devmode,
8090                                            struct security_descriptor *secdesc,
8091                                            struct spoolss_UserLevelCtr *user_ctr,
8092                                            struct policy_handle *handle)
8093 {
8094         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8095         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8096         int     snum;
8097         WERROR err = WERR_OK;
8098
8099         /* samba does not have a concept of local, non-shared printers yet, so
8100          * make sure we always setup sharename - gd */
8101         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8102             (info2->printername != NULL && info2->printername[0] != '\0')) {
8103                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8104                         "no sharename has been set, setting printername %s as sharename\n",
8105                         info2->printername));
8106                 info2->sharename = info2->printername;
8107         }
8108
8109         /* check to see if the printer already exists */
8110         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8111                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8112                         info2->sharename));
8113                 return WERR_PRINTER_ALREADY_EXISTS;
8114         }
8115
8116         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8117                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8118                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8119                                 info2->printername));
8120                         return WERR_PRINTER_ALREADY_EXISTS;
8121                 }
8122         }
8123
8124         /* validate printer info struct */
8125         if (!info2->printername || strlen(info2->printername) == 0) {
8126                 return WERR_INVALID_PRINTER_NAME;
8127         }
8128         if (!info2->portname || strlen(info2->portname) == 0) {
8129                 return WERR_UNKNOWN_PORT;
8130         }
8131         if (!info2->drivername || strlen(info2->drivername) == 0) {
8132                 return WERR_UNKNOWN_PRINTER_DRIVER;
8133         }
8134         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8135                 return WERR_UNKNOWN_PRINTPROCESSOR;
8136         }
8137
8138         /* FIXME!!!  smbd should check to see if the driver is installed before
8139            trying to add a printer like this  --jerry */
8140
8141         if (*lp_addprinter_command(talloc_tos()) ) {
8142                 char *raddr;
8143
8144                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8145                                                          p->mem_ctx);
8146                 if (raddr == NULL) {
8147                         return WERR_NOMEM;
8148                 }
8149
8150                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8151                                        info2, raddr,
8152                                        p->msg_ctx) ) {
8153                         return WERR_ACCESS_DENIED;
8154                 }
8155         } else {
8156                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8157                         "smb.conf parameter \"addprinter command\" is defined. This "
8158                         "parameter must exist for this call to succeed\n",
8159                         info2->sharename ));
8160         }
8161
8162         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8163                 return WERR_ACCESS_DENIED;
8164         }
8165
8166         /* you must be a printer admin to add a new printer */
8167         if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8168                                               p->msg_ctx,
8169                                               snum,
8170                                               PRINTER_ACCESS_ADMINISTER))) {
8171                 return WERR_ACCESS_DENIED;
8172         }
8173
8174         /*
8175          * Do sanity check on the requested changes for Samba.
8176          */
8177
8178         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8179                 return WERR_INVALID_PARAM;
8180         }
8181
8182         if (devmode == NULL) {
8183                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8184         }
8185
8186         err = update_dsspooler(p->mem_ctx,
8187                                get_session_info_system(),
8188                                p->msg_ctx,
8189                                0,
8190                                info2,
8191                                NULL);
8192         if (!W_ERROR_IS_OK(err)) {
8193                 return err;
8194         }
8195
8196         err = winreg_update_printer_internal(p->mem_ctx,
8197                                     get_session_info_system(),
8198                                     p->msg_ctx,
8199                                     info2->sharename,
8200                                     info2_mask,
8201                                     info2,
8202                                     devmode,
8203                                     secdesc);
8204         if (!W_ERROR_IS_OK(err)) {
8205                 return err;
8206         }
8207
8208         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8209         if (!W_ERROR_IS_OK(err)) {
8210                 /* Handle open failed - remove addition. */
8211                 ZERO_STRUCTP(handle);
8212                 return err;
8213         }
8214
8215         return WERR_OK;
8216 }
8217
8218 /****************************************************************
8219  _spoolss_AddPrinterEx
8220 ****************************************************************/
8221
8222 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8223                              struct spoolss_AddPrinterEx *r)
8224 {
8225         switch (r->in.info_ctr->level) {
8226         case 1:
8227                 /* we don't handle yet */
8228                 /* but I know what to do ... */
8229                 return WERR_UNKNOWN_LEVEL;
8230         case 2:
8231                 return spoolss_addprinterex_level_2(p, r->in.server,
8232                                                     r->in.info_ctr,
8233                                                     r->in.devmode_ctr->devmode,
8234                                                     r->in.secdesc_ctr->sd,
8235                                                     r->in.userlevel_ctr,
8236                                                     r->out.handle);
8237         default:
8238                 return WERR_UNKNOWN_LEVEL;
8239         }
8240 }
8241
8242 /****************************************************************
8243  _spoolss_AddPrinter
8244 ****************************************************************/
8245
8246 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8247                            struct spoolss_AddPrinter *r)
8248 {
8249         struct spoolss_AddPrinterEx a;
8250         struct spoolss_UserLevelCtr userlevel_ctr;
8251
8252         ZERO_STRUCT(userlevel_ctr);
8253
8254         userlevel_ctr.level = 1;
8255
8256         a.in.server             = r->in.server;
8257         a.in.info_ctr           = r->in.info_ctr;
8258         a.in.devmode_ctr        = r->in.devmode_ctr;
8259         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8260         a.in.userlevel_ctr      = &userlevel_ctr;
8261         a.out.handle            = r->out.handle;
8262
8263         return _spoolss_AddPrinterEx(p, &a);
8264 }
8265
8266 /****************************************************************
8267  _spoolss_AddPrinterDriverEx
8268 ****************************************************************/
8269
8270 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8271                                    struct spoolss_AddPrinterDriverEx *r)
8272 {
8273         WERROR err = WERR_OK;
8274         const char *driver_name = NULL;
8275         uint32_t version;
8276         const char *fn;
8277
8278         switch (p->opnum) {
8279                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8280                         fn = "_spoolss_AddPrinterDriver";
8281                         break;
8282                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8283                         fn = "_spoolss_AddPrinterDriverEx";
8284                         break;
8285                 default:
8286                         return WERR_INVALID_PARAM;
8287         }
8288
8289         /*
8290          * we only support the semantics of AddPrinterDriver()
8291          * i.e. only copy files that are newer than existing ones
8292          */
8293
8294         if (r->in.flags == 0) {
8295                 return WERR_INVALID_PARAM;
8296         }
8297
8298         if (r->in.flags != APD_COPY_NEW_FILES) {
8299                 return WERR_ACCESS_DENIED;
8300         }
8301
8302         /* FIXME */
8303         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8304                 /* Clever hack from Martin Zielinski <mz@seh.de>
8305                  * to allow downgrade from level 8 (Vista).
8306                  */
8307                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8308                         r->in.info_ctr->level));
8309                 return WERR_UNKNOWN_LEVEL;
8310         }
8311
8312         DEBUG(5,("Cleaning driver's information\n"));
8313         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8314         if (!W_ERROR_IS_OK(err))
8315                 goto done;
8316
8317         DEBUG(5,("Moving driver to final destination\n"));
8318         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8319         if (!W_ERROR_IS_OK(err)) {
8320                 goto done;
8321         }
8322
8323         err = winreg_add_driver_internal(p->mem_ctx,
8324                                 get_session_info_system(),
8325                                 p->msg_ctx,
8326                                 r->in.info_ctr,
8327                                 &driver_name,
8328                                 &version);
8329         if (!W_ERROR_IS_OK(err)) {
8330                 goto done;
8331         }
8332
8333         /*
8334          * I think this is where he DrvUpgradePrinter() hook would be
8335          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8336          * server.  Right now, we just need to send ourselves a message
8337          * to update each printer bound to this driver.   --jerry
8338          */
8339
8340         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8341                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8342                         fn, driver_name));
8343         }
8344
8345 done:
8346         return err;
8347 }
8348
8349 /****************************************************************
8350  _spoolss_AddPrinterDriver
8351 ****************************************************************/
8352
8353 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8354                                  struct spoolss_AddPrinterDriver *r)
8355 {
8356         struct spoolss_AddPrinterDriverEx a;
8357
8358         switch (r->in.info_ctr->level) {
8359         case 2:
8360         case 3:
8361         case 4:
8362         case 5:
8363                 break;
8364         default:
8365                 return WERR_UNKNOWN_LEVEL;
8366         }
8367
8368         a.in.servername         = r->in.servername;
8369         a.in.info_ctr           = r->in.info_ctr;
8370         a.in.flags              = APD_COPY_NEW_FILES;
8371
8372         return _spoolss_AddPrinterDriverEx(p, &a);
8373 }
8374
8375 /****************************************************************************
8376 ****************************************************************************/
8377
8378 struct _spoolss_paths {
8379         int type;
8380         const char *share;
8381         const char *dir;
8382 };
8383
8384 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8385
8386 static const struct _spoolss_paths spoolss_paths[]= {
8387         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8388         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8389 };
8390
8391 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8392                                           const char *servername,
8393                                           const char *environment,
8394                                           int component,
8395                                           char **path)
8396 {
8397         const char *pservername = NULL;
8398         const char *long_archi;
8399         const char *short_archi;
8400
8401         *path = NULL;
8402
8403         /* environment may be empty */
8404         if (environment && strlen(environment)) {
8405                 long_archi = environment;
8406         } else {
8407                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8408                                                   "spoolss", "architecture",
8409                                                   SPOOLSS_ARCHITECTURE_NT_X86);
8410         }
8411
8412         /* servername may be empty */
8413         if (servername && strlen(servername)) {
8414                 pservername = canon_servername(servername);
8415
8416                 if (!is_myname_or_ipaddr(pservername)) {
8417                         return WERR_INVALID_PARAM;
8418                 }
8419         }
8420
8421         if (!(short_archi = get_short_archi(long_archi))) {
8422                 return WERR_INVALID_ENVIRONMENT;
8423         }
8424
8425         switch (component) {
8426         case SPOOLSS_PRTPROCS_PATH:
8427         case SPOOLSS_DRIVER_PATH:
8428                 if (pservername) {
8429                         *path = talloc_asprintf(mem_ctx,
8430                                         "\\\\%s\\%s\\%s",
8431                                         pservername,
8432                                         spoolss_paths[component].share,
8433                                         short_archi);
8434                 } else {
8435                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8436                                         SPOOLSS_DEFAULT_SERVER_PATH,
8437                                         spoolss_paths[component].dir,
8438                                         short_archi);
8439                 }
8440                 break;
8441         default:
8442                 return WERR_INVALID_PARAM;
8443         }
8444
8445         if (!*path) {
8446                 return WERR_NOMEM;
8447         }
8448
8449         return WERR_OK;
8450 }
8451
8452 /****************************************************************************
8453 ****************************************************************************/
8454
8455 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8456                                           const char *servername,
8457                                           const char *environment,
8458                                           struct spoolss_DriverDirectoryInfo1 *r)
8459 {
8460         WERROR werr;
8461         char *path = NULL;
8462
8463         werr = compose_spoolss_server_path(mem_ctx,
8464                                            servername,
8465                                            environment,
8466                                            SPOOLSS_DRIVER_PATH,
8467                                            &path);
8468         if (!W_ERROR_IS_OK(werr)) {
8469                 return werr;
8470         }
8471
8472         DEBUG(4,("printer driver directory: [%s]\n", path));
8473
8474         r->directory_name = path;
8475
8476         return WERR_OK;
8477 }
8478
8479 /****************************************************************
8480  _spoolss_GetPrinterDriverDirectory
8481 ****************************************************************/
8482
8483 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8484                                           struct spoolss_GetPrinterDriverDirectory *r)
8485 {
8486         WERROR werror;
8487
8488         /* that's an [in out] buffer */
8489
8490         if (!r->in.buffer && (r->in.offered != 0)) {
8491                 return WERR_INVALID_PARAM;
8492         }
8493
8494         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8495                 r->in.level));
8496
8497         *r->out.needed = 0;
8498
8499         /* r->in.level is ignored */
8500
8501         werror = getprinterdriverdir_level_1(p->mem_ctx,
8502                                              r->in.server,
8503                                              r->in.environment,
8504                                              &r->out.info->info1);
8505         if (!W_ERROR_IS_OK(werror)) {
8506                 TALLOC_FREE(r->out.info);
8507                 return werror;
8508         }
8509
8510         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8511                                                r->out.info, r->in.level);
8512         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8513
8514         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8515 }
8516
8517 /****************************************************************
8518  _spoolss_EnumPrinterData
8519 ****************************************************************/
8520
8521 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8522                                 struct spoolss_EnumPrinterData *r)
8523 {
8524         WERROR result;
8525         struct spoolss_EnumPrinterDataEx r2;
8526         uint32_t count;
8527         struct spoolss_PrinterEnumValues *info, *val = NULL;
8528         uint32_t needed;
8529
8530         r2.in.handle    = r->in.handle;
8531         r2.in.key_name  = "PrinterDriverData";
8532         r2.in.offered   = 0;
8533         r2.out.count    = &count;
8534         r2.out.info     = &info;
8535         r2.out.needed   = &needed;
8536
8537         result = _spoolss_EnumPrinterDataEx(p, &r2);
8538         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8539                 r2.in.offered = needed;
8540                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8541         }
8542         if (!W_ERROR_IS_OK(result)) {
8543                 return result;
8544         }
8545
8546         /*
8547          * The NT machine wants to know the biggest size of value and data
8548          *
8549          * cf: MSDN EnumPrinterData remark section
8550          */
8551
8552         if (!r->in.value_offered && !r->in.data_offered) {
8553                 uint32_t biggest_valuesize = 0;
8554                 uint32_t biggest_datasize = 0;
8555                 int i, name_length;
8556
8557                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8558
8559                 for (i=0; i<count; i++) {
8560
8561                         name_length = strlen(info[i].value_name);
8562                         if (strlen(info[i].value_name) > biggest_valuesize) {
8563                                 biggest_valuesize = name_length;
8564                         }
8565
8566                         if (info[i].data_length > biggest_datasize) {
8567                                 biggest_datasize = info[i].data_length;
8568                         }
8569
8570                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8571                                 biggest_datasize));
8572                 }
8573
8574                 /* the value is an UNICODE string but real_value_size is the length
8575                    in bytes including the trailing 0 */
8576
8577                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8578                 *r->out.data_needed  = biggest_datasize;
8579
8580                 DEBUG(6,("final values: [%d], [%d]\n",
8581                         *r->out.value_needed, *r->out.data_needed));
8582
8583                 return WERR_OK;
8584         }
8585
8586         if (r->in.enum_index < count) {
8587                 val = &info[r->in.enum_index];
8588         }
8589
8590         if (val == NULL) {
8591                 /* out_value should default to "" or else NT4 has
8592                    problems unmarshalling the response */
8593
8594                 if (r->in.value_offered) {
8595                         *r->out.value_needed = 1;
8596                         r->out.value_name = talloc_strdup(r, "");
8597                         if (!r->out.value_name) {
8598                                 return WERR_NOMEM;
8599                         }
8600                 } else {
8601                         r->out.value_name = NULL;
8602                         *r->out.value_needed = 0;
8603                 }
8604
8605                 /* the data is counted in bytes */
8606
8607                 *r->out.data_needed = r->in.data_offered;
8608
8609                 result = WERR_NO_MORE_ITEMS;
8610         } else {
8611                 /*
8612                  * the value is:
8613                  * - counted in bytes in the request
8614                  * - counted in UNICODE chars in the max reply
8615                  * - counted in bytes in the real size
8616                  *
8617                  * take a pause *before* coding not *during* coding
8618                  */
8619
8620                 /* name */
8621                 if (r->in.value_offered) {
8622                         r->out.value_name = talloc_strdup(r, val->value_name);
8623                         if (!r->out.value_name) {
8624                                 return WERR_NOMEM;
8625                         }
8626                         *r->out.value_needed = val->value_name_len;
8627                 } else {
8628                         r->out.value_name = NULL;
8629                         *r->out.value_needed = 0;
8630                 }
8631
8632                 /* type */
8633
8634                 *r->out.type = val->type;
8635
8636                 /* data - counted in bytes */
8637
8638                 /*
8639                  * See the section "Dynamically Typed Query Parameters"
8640                  * in MS-RPRN.
8641                  */
8642
8643                 if (r->out.data && val->data && val->data->data &&
8644                                 val->data_length && r->in.data_offered) {
8645                         memcpy(r->out.data, val->data->data,
8646                                 MIN(val->data_length,r->in.data_offered));
8647                 }
8648
8649                 *r->out.data_needed = val->data_length;
8650
8651                 result = WERR_OK;
8652         }
8653
8654         return result;
8655 }
8656
8657 /****************************************************************
8658  _spoolss_SetPrinterData
8659 ****************************************************************/
8660
8661 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8662                                struct spoolss_SetPrinterData *r)
8663 {
8664         struct spoolss_SetPrinterDataEx r2;
8665
8666         r2.in.handle            = r->in.handle;
8667         r2.in.key_name          = "PrinterDriverData";
8668         r2.in.value_name        = r->in.value_name;
8669         r2.in.type              = r->in.type;
8670         r2.in.data              = r->in.data;
8671         r2.in.offered           = r->in.offered;
8672
8673         return _spoolss_SetPrinterDataEx(p, &r2);
8674 }
8675
8676 /****************************************************************
8677  _spoolss_ResetPrinter
8678 ****************************************************************/
8679
8680 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8681                              struct spoolss_ResetPrinter *r)
8682 {
8683         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8684         int             snum;
8685
8686         DEBUG(5,("_spoolss_ResetPrinter\n"));
8687
8688         /*
8689          * All we do is to check to see if the handle and queue is valid.
8690          * This call really doesn't mean anything to us because we only
8691          * support RAW printing.   --jerry
8692          */
8693
8694         if (!Printer) {
8695                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8696                         OUR_HANDLE(r->in.handle)));
8697                 return WERR_BADFID;
8698         }
8699
8700         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8701                 return WERR_BADFID;
8702
8703
8704         /* blindly return success */
8705         return WERR_OK;
8706 }
8707
8708 /****************************************************************
8709  _spoolss_DeletePrinterData
8710 ****************************************************************/
8711
8712 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8713                                   struct spoolss_DeletePrinterData *r)
8714 {
8715         struct spoolss_DeletePrinterDataEx r2;
8716
8717         r2.in.handle            = r->in.handle;
8718         r2.in.key_name          = "PrinterDriverData";
8719         r2.in.value_name        = r->in.value_name;
8720
8721         return _spoolss_DeletePrinterDataEx(p, &r2);
8722 }
8723
8724 /****************************************************************
8725  _spoolss_AddForm
8726 ****************************************************************/
8727
8728 WERROR _spoolss_AddForm(struct pipes_struct *p,
8729                         struct spoolss_AddForm *r)
8730 {
8731         struct spoolss_AddFormInfo1 *form;
8732         int snum = -1;
8733         WERROR status = WERR_OK;
8734         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8735         struct dcerpc_binding_handle *b;
8736         TALLOC_CTX *tmp_ctx = NULL;
8737
8738         DEBUG(5,("_spoolss_AddForm\n"));
8739
8740         if (!Printer) {
8741                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8742                         OUR_HANDLE(r->in.handle)));
8743                 return WERR_BADFID;
8744         }
8745
8746         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8747            and not a printer admin, then fail */
8748
8749         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8750             !security_token_has_privilege(p->session_info->security_token,
8751                                           SEC_PRIV_PRINT_OPERATOR)) {
8752                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8753                 return WERR_ACCESS_DENIED;
8754         }
8755
8756         if (r->in.info_ctr->level != 1) {
8757                 return WERR_INVALID_LEVEL;
8758         }
8759
8760         form = r->in.info_ctr->info.info1;
8761         if (!form) {
8762                 return WERR_INVALID_PARAM;
8763         }
8764
8765         switch (form->flags) {
8766         case SPOOLSS_FORM_USER:
8767         case SPOOLSS_FORM_BUILTIN:
8768         case SPOOLSS_FORM_PRINTER:
8769                 break;
8770         default:
8771                 return WERR_INVALID_PARAM;
8772         }
8773
8774         tmp_ctx = talloc_new(p->mem_ctx);
8775         if (!tmp_ctx) {
8776                 return WERR_NOMEM;
8777         }
8778
8779         status = winreg_printer_binding_handle(tmp_ctx,
8780                                                get_session_info_system(),
8781                                                p->msg_ctx,
8782                                                &b);
8783         if (!W_ERROR_IS_OK(status)) {
8784                 goto done;
8785         }
8786
8787         status = winreg_printer_addform1(tmp_ctx, b, form);
8788         if (!W_ERROR_IS_OK(status)) {
8789                 goto done;
8790         }
8791
8792         /*
8793          * ChangeID must always be set if this is a printer
8794          */
8795         if (Printer->printer_type == SPLHND_PRINTER) {
8796                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8797                         status = WERR_BADFID;
8798                         goto done;
8799                 }
8800
8801                 status = winreg_printer_update_changeid(tmp_ctx, b,
8802                                                         lp_const_servicename(snum));
8803         }
8804
8805 done:
8806         talloc_free(tmp_ctx);
8807         return status;
8808 }
8809
8810 /****************************************************************
8811  _spoolss_DeleteForm
8812 ****************************************************************/
8813
8814 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8815                            struct spoolss_DeleteForm *r)
8816 {
8817         const char *form_name = r->in.form_name;
8818         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8819         int snum = -1;
8820         WERROR status = WERR_OK;
8821         struct dcerpc_binding_handle *b;
8822         TALLOC_CTX *tmp_ctx = NULL;
8823
8824         DEBUG(5,("_spoolss_DeleteForm\n"));
8825
8826         if (!Printer) {
8827                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8828                         OUR_HANDLE(r->in.handle)));
8829                 return WERR_BADFID;
8830         }
8831
8832         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8833             !security_token_has_privilege(p->session_info->security_token,
8834                                           SEC_PRIV_PRINT_OPERATOR)) {
8835                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8836                 return WERR_ACCESS_DENIED;
8837         }
8838
8839         tmp_ctx = talloc_new(p->mem_ctx);
8840         if (!tmp_ctx) {
8841                 return WERR_NOMEM;
8842         }
8843
8844         status = winreg_printer_binding_handle(tmp_ctx,
8845                                                get_session_info_system(),
8846                                                p->msg_ctx,
8847                                                &b);
8848         if (!W_ERROR_IS_OK(status)) {
8849                 goto done;
8850         }
8851
8852         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8853         if (!W_ERROR_IS_OK(status)) {
8854                 goto done;
8855         }
8856
8857         /*
8858          * ChangeID must always be set if this is a printer
8859          */
8860         if (Printer->printer_type == SPLHND_PRINTER) {
8861                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8862                         status = WERR_BADFID;
8863                         goto done;
8864                 }
8865
8866                 status = winreg_printer_update_changeid(tmp_ctx, b,
8867                                                         lp_const_servicename(snum));
8868         }
8869
8870 done:
8871         talloc_free(tmp_ctx);
8872         return status;
8873 }
8874
8875 /****************************************************************
8876  _spoolss_SetForm
8877 ****************************************************************/
8878
8879 WERROR _spoolss_SetForm(struct pipes_struct *p,
8880                         struct spoolss_SetForm *r)
8881 {
8882         struct spoolss_AddFormInfo1 *form;
8883         const char *form_name = r->in.form_name;
8884         int snum = -1;
8885         WERROR status = WERR_OK;
8886         struct dcerpc_binding_handle *b;
8887         TALLOC_CTX *tmp_ctx = NULL;
8888
8889         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8890
8891         DEBUG(5,("_spoolss_SetForm\n"));
8892
8893         if (!Printer) {
8894                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8895                         OUR_HANDLE(r->in.handle)));
8896                 return WERR_BADFID;
8897         }
8898
8899         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8900            and not a printer admin, then fail */
8901
8902         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8903              !security_token_has_privilege(p->session_info->security_token,
8904                                            SEC_PRIV_PRINT_OPERATOR)) {
8905                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8906                 return WERR_ACCESS_DENIED;
8907         }
8908
8909         if (r->in.info_ctr->level != 1) {
8910                 return WERR_INVALID_LEVEL;
8911         }
8912
8913         form = r->in.info_ctr->info.info1;
8914         if (!form) {
8915                 return WERR_INVALID_PARAM;
8916         }
8917
8918         tmp_ctx = talloc_new(p->mem_ctx);
8919         if (!tmp_ctx) {
8920                 return WERR_NOMEM;
8921         }
8922
8923         status = winreg_printer_binding_handle(tmp_ctx,
8924                                                get_session_info_system(),
8925                                                p->msg_ctx,
8926                                                &b);
8927         if (!W_ERROR_IS_OK(status)) {
8928                 goto done;
8929         }
8930
8931         status = winreg_printer_setform1(tmp_ctx, b,
8932                                          form_name,
8933                                          form);
8934         if (!W_ERROR_IS_OK(status)) {
8935                 goto done;
8936         }
8937
8938         /*
8939          * ChangeID must always be set if this is a printer
8940          */
8941         if (Printer->printer_type == SPLHND_PRINTER) {
8942                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8943                         status = WERR_BADFID;
8944                         goto done;
8945                 }
8946
8947                 status = winreg_printer_update_changeid(tmp_ctx, b,
8948                                                         lp_const_servicename(snum));
8949         }
8950
8951 done:
8952         talloc_free(tmp_ctx);
8953         return status;
8954 }
8955
8956 /****************************************************************************
8957  fill_print_processor1
8958 ****************************************************************************/
8959
8960 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8961                                     struct spoolss_PrintProcessorInfo1 *r,
8962                                     const char *print_processor_name)
8963 {
8964         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8965         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8966
8967         return WERR_OK;
8968 }
8969
8970 /****************************************************************************
8971  enumprintprocessors level 1.
8972 ****************************************************************************/
8973
8974 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8975                                           union spoolss_PrintProcessorInfo **info_p,
8976                                           uint32_t *count)
8977 {
8978         union spoolss_PrintProcessorInfo *info;
8979         WERROR result;
8980
8981         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8982         W_ERROR_HAVE_NO_MEMORY(info);
8983
8984         *count = 1;
8985
8986         result = fill_print_processor1(info, &info[0].info1, "winprint");
8987         if (!W_ERROR_IS_OK(result)) {
8988                 goto out;
8989         }
8990
8991  out:
8992         if (!W_ERROR_IS_OK(result)) {
8993                 TALLOC_FREE(info);
8994                 *count = 0;
8995                 return result;
8996         }
8997
8998         *info_p = info;
8999
9000         return WERR_OK;
9001 }
9002
9003 /****************************************************************
9004  _spoolss_EnumPrintProcessors
9005 ****************************************************************/
9006
9007 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9008                                     struct spoolss_EnumPrintProcessors *r)
9009 {
9010         WERROR result;
9011
9012         /* that's an [in out] buffer */
9013
9014         if (!r->in.buffer && (r->in.offered != 0)) {
9015                 return WERR_INVALID_PARAM;
9016         }
9017
9018         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9019
9020         /*
9021          * Enumerate the print processors ...
9022          *
9023          * Just reply with "winprint", to keep NT happy
9024          * and I can use my nice printer checker.
9025          */
9026
9027         *r->out.count = 0;
9028         *r->out.needed = 0;
9029         *r->out.info = NULL;
9030
9031         if (!get_short_archi(r->in.environment)) {
9032                 return WERR_INVALID_ENVIRONMENT;
9033         }
9034
9035         switch (r->in.level) {
9036         case 1:
9037                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9038                                                      r->out.count);
9039                 break;
9040         default:
9041                 return WERR_UNKNOWN_LEVEL;
9042         }
9043
9044         if (!W_ERROR_IS_OK(result)) {
9045                 return result;
9046         }
9047
9048         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9049                                                      spoolss_EnumPrintProcessors,
9050                                                      *r->out.info, r->in.level,
9051                                                      *r->out.count);
9052         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9053         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9054
9055         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9056 }
9057
9058 /****************************************************************************
9059  fill_printprocdatatype1
9060 ****************************************************************************/
9061
9062 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9063                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9064                                       const char *name_array)
9065 {
9066         r->name_array = talloc_strdup(mem_ctx, name_array);
9067         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9068
9069         return WERR_OK;
9070 }
9071
9072 /****************************************************************************
9073  enumprintprocdatatypes level 1.
9074 ****************************************************************************/
9075
9076 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9077                                              union spoolss_PrintProcDataTypesInfo **info_p,
9078                                              uint32_t *count)
9079 {
9080         WERROR result;
9081         union spoolss_PrintProcDataTypesInfo *info;
9082
9083         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9084         W_ERROR_HAVE_NO_MEMORY(info);
9085
9086         *count = 1;
9087
9088         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9089         if (!W_ERROR_IS_OK(result)) {
9090                 goto out;
9091         }
9092
9093  out:
9094         if (!W_ERROR_IS_OK(result)) {
9095                 TALLOC_FREE(info);
9096                 *count = 0;
9097                 return result;
9098         }
9099
9100         *info_p = info;
9101
9102         return WERR_OK;
9103 }
9104
9105 /****************************************************************
9106  _spoolss_EnumPrintProcDataTypes
9107 ****************************************************************/
9108
9109 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9110                                        struct spoolss_EnumPrintProcDataTypes *r)
9111 {
9112         WERROR result;
9113
9114         /* that's an [in out] buffer */
9115
9116         if (!r->in.buffer && (r->in.offered != 0)) {
9117                 return WERR_INVALID_PARAM;
9118         }
9119
9120         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9121
9122         *r->out.count = 0;
9123         *r->out.needed = 0;
9124         *r->out.info = NULL;
9125
9126         if (r->in.print_processor_name == NULL ||
9127             !strequal(r->in.print_processor_name, "winprint")) {
9128                 return WERR_UNKNOWN_PRINTPROCESSOR;
9129         }
9130
9131         switch (r->in.level) {
9132         case 1:
9133                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9134                                                         r->out.count);
9135                 break;
9136         default:
9137                 return WERR_UNKNOWN_LEVEL;
9138         }
9139
9140         if (!W_ERROR_IS_OK(result)) {
9141                 return result;
9142         }
9143
9144         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9145                                                      spoolss_EnumPrintProcDataTypes,
9146                                                      *r->out.info, r->in.level,
9147                                                      *r->out.count);
9148         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9149         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9150
9151         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9152 }
9153
9154 /****************************************************************************
9155  fill_monitor_1
9156 ****************************************************************************/
9157
9158 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9159                              struct spoolss_MonitorInfo1 *r,
9160                              const char *monitor_name)
9161 {
9162         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9163         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9164
9165         return WERR_OK;
9166 }
9167
9168 /****************************************************************************
9169  fill_monitor_2
9170 ****************************************************************************/
9171
9172 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9173                              struct spoolss_MonitorInfo2 *r,
9174                              const char *monitor_name,
9175                              const char *environment,
9176                              const char *dll_name)
9177 {
9178         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9179         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9180         r->environment                  = talloc_strdup(mem_ctx, environment);
9181         W_ERROR_HAVE_NO_MEMORY(r->environment);
9182         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9183         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9184
9185         return WERR_OK;
9186 }
9187
9188 /****************************************************************************
9189  enumprintmonitors level 1.
9190 ****************************************************************************/
9191
9192 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9193                                         union spoolss_MonitorInfo **info_p,
9194                                         uint32_t *count)
9195 {
9196         union spoolss_MonitorInfo *info;
9197         WERROR result = WERR_OK;
9198
9199         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9200         W_ERROR_HAVE_NO_MEMORY(info);
9201
9202         *count = 2;
9203
9204         result = fill_monitor_1(info, &info[0].info1,
9205                                 SPL_LOCAL_PORT);
9206         if (!W_ERROR_IS_OK(result)) {
9207                 goto out;
9208         }
9209
9210         result = fill_monitor_1(info, &info[1].info1,
9211                                 SPL_TCPIP_PORT);
9212         if (!W_ERROR_IS_OK(result)) {
9213                 goto out;
9214         }
9215
9216 out:
9217         if (!W_ERROR_IS_OK(result)) {
9218                 TALLOC_FREE(info);
9219                 *count = 0;
9220                 return result;
9221         }
9222
9223         *info_p = info;
9224
9225         return WERR_OK;
9226 }
9227
9228 /****************************************************************************
9229  enumprintmonitors level 2.
9230 ****************************************************************************/
9231
9232 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9233                                         union spoolss_MonitorInfo **info_p,
9234                                         uint32_t *count)
9235 {
9236         union spoolss_MonitorInfo *info;
9237         WERROR result = WERR_OK;
9238
9239         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9240         W_ERROR_HAVE_NO_MEMORY(info);
9241
9242         *count = 2;
9243
9244         result = fill_monitor_2(info, &info[0].info2,
9245                                 SPL_LOCAL_PORT,
9246                                 "Windows NT X86", /* FIXME */
9247                                 "localmon.dll");
9248         if (!W_ERROR_IS_OK(result)) {
9249                 goto out;
9250         }
9251
9252         result = fill_monitor_2(info, &info[1].info2,
9253                                 SPL_TCPIP_PORT,
9254                                 "Windows NT X86", /* FIXME */
9255                                 "tcpmon.dll");
9256         if (!W_ERROR_IS_OK(result)) {
9257                 goto out;
9258         }
9259
9260 out:
9261         if (!W_ERROR_IS_OK(result)) {
9262                 TALLOC_FREE(info);
9263                 *count = 0;
9264                 return result;
9265         }
9266
9267         *info_p = info;
9268
9269         return WERR_OK;
9270 }
9271
9272 /****************************************************************
9273  _spoolss_EnumMonitors
9274 ****************************************************************/
9275
9276 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9277                              struct spoolss_EnumMonitors *r)
9278 {
9279         WERROR result;
9280
9281         /* that's an [in out] buffer */
9282
9283         if (!r->in.buffer && (r->in.offered != 0)) {
9284                 return WERR_INVALID_PARAM;
9285         }
9286
9287         DEBUG(5,("_spoolss_EnumMonitors\n"));
9288
9289         /*
9290          * Enumerate the print monitors ...
9291          *
9292          * Just reply with "Local Port", to keep NT happy
9293          * and I can use my nice printer checker.
9294          */
9295
9296         *r->out.count = 0;
9297         *r->out.needed = 0;
9298         *r->out.info = NULL;
9299
9300         switch (r->in.level) {
9301         case 1:
9302                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9303                                                    r->out.count);
9304                 break;
9305         case 2:
9306                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9307                                                    r->out.count);
9308                 break;
9309         default:
9310                 return WERR_UNKNOWN_LEVEL;
9311         }
9312
9313         if (!W_ERROR_IS_OK(result)) {
9314                 return result;
9315         }
9316
9317         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9318                                                      spoolss_EnumMonitors,
9319                                                      *r->out.info, r->in.level,
9320                                                      *r->out.count);
9321         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9322         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9323
9324         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9325 }
9326
9327 /****************************************************************************
9328 ****************************************************************************/
9329
9330 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9331                              const print_queue_struct *queue,
9332                              int count, int snum,
9333                              struct spoolss_PrinterInfo2 *pinfo2,
9334                              uint32_t jobid,
9335                              struct spoolss_JobInfo1 *r)
9336 {
9337         int i = 0;
9338         bool found = false;
9339
9340         for (i=0; i<count; i++) {
9341                 if (queue[i].sysjob == (int)jobid) {
9342                         found = true;
9343                         break;
9344                 }
9345         }
9346
9347         if (found == false) {
9348                 /* NT treats not found as bad param... yet another bad choice */
9349                 return WERR_INVALID_PARAM;
9350         }
9351
9352         return fill_job_info1(mem_ctx,
9353                               r,
9354                               &queue[i],
9355                               i,
9356                               snum,
9357                               pinfo2);
9358 }
9359
9360 /****************************************************************************
9361 ****************************************************************************/
9362
9363 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9364                              const print_queue_struct *queue,
9365                              int count, int snum,
9366                              struct spoolss_PrinterInfo2 *pinfo2,
9367                              uint32_t jobid,
9368                              struct spoolss_JobInfo2 *r)
9369 {
9370         int i = 0;
9371         bool found = false;
9372         struct spoolss_DeviceMode *devmode;
9373         WERROR result;
9374
9375         for (i=0; i<count; i++) {
9376                 if (queue[i].sysjob == (int)jobid) {
9377                         found = true;
9378                         break;
9379                 }
9380         }
9381
9382         if (found == false) {
9383                 /* NT treats not found as bad param... yet another bad
9384                    choice */
9385                 return WERR_INVALID_PARAM;
9386         }
9387
9388         /*
9389          * if the print job does not have a DEVMODE associated with it,
9390          * just use the one for the printer. A NULL devicemode is not
9391          *  a failure condition
9392          */
9393
9394         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9395         if (!devmode) {
9396                 result = spoolss_create_default_devmode(mem_ctx,
9397                                                 pinfo2->printername,
9398                                                 &devmode);
9399                 if (!W_ERROR_IS_OK(result)) {
9400                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9401                         return result;
9402                 }
9403         }
9404
9405         return fill_job_info2(mem_ctx,
9406                               r,
9407                               &queue[i],
9408                               i,
9409                               snum,
9410                               pinfo2,
9411                               devmode);
9412 }
9413
9414 /****************************************************************
9415  _spoolss_GetJob
9416 ****************************************************************/
9417
9418 WERROR _spoolss_GetJob(struct pipes_struct *p,
9419                        struct spoolss_GetJob *r)
9420 {
9421         WERROR result = WERR_OK;
9422         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9423         int snum;
9424         int count;
9425         print_queue_struct      *queue = NULL;
9426         print_status_struct prt_status;
9427
9428         /* that's an [in out] buffer */
9429
9430         if (!r->in.buffer && (r->in.offered != 0)) {
9431                 return WERR_INVALID_PARAM;
9432         }
9433
9434         DEBUG(5,("_spoolss_GetJob\n"));
9435
9436         *r->out.needed = 0;
9437
9438         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9439                 return WERR_BADFID;
9440         }
9441
9442         result = winreg_get_printer_internal(p->mem_ctx,
9443                                     get_session_info_system(),
9444                                     p->msg_ctx,
9445                                     lp_const_servicename(snum),
9446                                     &pinfo2);
9447         if (!W_ERROR_IS_OK(result)) {
9448                 return result;
9449         }
9450
9451         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9452
9453         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9454                      count, prt_status.status, prt_status.message));
9455
9456         switch (r->in.level) {
9457         case 1:
9458                 result = getjob_level_1(p->mem_ctx,
9459                                         queue, count, snum, pinfo2,
9460                                         r->in.job_id, &r->out.info->info1);
9461                 break;
9462         case 2:
9463                 result = getjob_level_2(p->mem_ctx,
9464                                         queue, count, snum, pinfo2,
9465                                         r->in.job_id, &r->out.info->info2);
9466                 break;
9467         default:
9468                 result = WERR_UNKNOWN_LEVEL;
9469                 break;
9470         }
9471
9472         SAFE_FREE(queue);
9473         TALLOC_FREE(pinfo2);
9474
9475         if (!W_ERROR_IS_OK(result)) {
9476                 TALLOC_FREE(r->out.info);
9477                 return result;
9478         }
9479
9480         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9481                                                                                    r->in.level);
9482         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9483
9484         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9485 }
9486
9487 /****************************************************************
9488  _spoolss_GetPrinterDataEx
9489 ****************************************************************/
9490
9491 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9492                                  struct spoolss_GetPrinterDataEx *r)
9493 {
9494
9495         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9496         const char *printer;
9497         int                     snum = 0;
9498         WERROR result = WERR_OK;
9499         DATA_BLOB blob;
9500         enum winreg_Type val_type = REG_NONE;
9501         uint8_t *val_data = NULL;
9502         uint32_t val_size = 0;
9503         struct dcerpc_binding_handle *b;
9504         TALLOC_CTX *tmp_ctx;
9505
9506         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9507
9508         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9509                 r->in.key_name, r->in.value_name));
9510
9511         /* in case of problem, return some default values */
9512
9513         *r->out.needed  = 0;
9514         *r->out.type    = REG_NONE;
9515
9516         tmp_ctx = talloc_new(p->mem_ctx);
9517         if (!tmp_ctx) {
9518                 return WERR_NOMEM;
9519         }
9520
9521         if (!Printer) {
9522                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9523                         OUR_HANDLE(r->in.handle)));
9524                 result = WERR_BADFID;
9525                 goto done;
9526         }
9527
9528         /* check to see if the keyname is valid */
9529         if (!strlen(r->in.key_name)) {
9530                 result = WERR_INVALID_PARAM;
9531                 goto done;
9532         }
9533
9534         /* Is the handle to a printer or to the server? */
9535
9536         if (Printer->printer_type == SPLHND_SERVER) {
9537
9538                 union spoolss_PrinterData data;
9539
9540                 result = getprinterdata_printer_server(tmp_ctx,
9541                                                        r->in.value_name,
9542                                                        r->out.type,
9543                                                        &data);
9544                 if (!W_ERROR_IS_OK(result)) {
9545                         goto done;
9546                 }
9547
9548                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9549                                                   *r->out.type, &data);
9550                 if (!W_ERROR_IS_OK(result)) {
9551                         goto done;
9552                 }
9553
9554                 *r->out.needed = blob.length;
9555
9556                 if (r->in.offered >= *r->out.needed) {
9557                         memcpy(r->out.data, blob.data, blob.length);
9558                 }
9559
9560                 result = WERR_OK;
9561                 goto done;
9562         }
9563
9564         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9565                 result = WERR_BADFID;
9566                 goto done;
9567         }
9568         printer = lp_const_servicename(snum);
9569
9570         result = winreg_printer_binding_handle(tmp_ctx,
9571                                                get_session_info_system(),
9572                                                p->msg_ctx,
9573                                                &b);
9574         if (!W_ERROR_IS_OK(result)) {
9575                 goto done;
9576         }
9577
9578         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9579         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9580             strequal(r->in.value_name, "ChangeId")) {
9581                 *r->out.type = REG_DWORD;
9582                 *r->out.needed = 4;
9583                 if (r->in.offered >= *r->out.needed) {
9584                         uint32_t changeid = 0;
9585
9586                         result = winreg_printer_get_changeid(tmp_ctx, b,
9587                                                              printer,
9588                                                              &changeid);
9589                         if (!W_ERROR_IS_OK(result)) {
9590                                 goto done;
9591                         }
9592
9593                         SIVAL(r->out.data, 0, changeid);
9594                         result = WERR_OK;
9595                 }
9596                 goto done;
9597         }
9598
9599         result = winreg_get_printer_dataex(tmp_ctx, b,
9600                                            printer,
9601                                            r->in.key_name,
9602                                            r->in.value_name,
9603                                            &val_type,
9604                                            &val_data,
9605                                            &val_size);
9606         if (!W_ERROR_IS_OK(result)) {
9607                 goto done;
9608         }
9609
9610         *r->out.needed = val_size;
9611         *r->out.type = val_type;
9612
9613         if (r->in.offered >= *r->out.needed) {
9614                 memcpy(r->out.data, val_data, val_size);
9615         }
9616
9617 done:
9618         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9619
9620         if (W_ERROR_IS_OK(result)) {
9621                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9622         }
9623
9624         talloc_free(tmp_ctx);
9625         return result;
9626 }
9627
9628 /****************************************************************
9629  _spoolss_SetPrinterDataEx
9630 ****************************************************************/
9631
9632 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9633                                  struct spoolss_SetPrinterDataEx *r)
9634 {
9635         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9636         int                     snum = 0;
9637         WERROR                  result = WERR_OK;
9638         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9639         char                    *oid_string;
9640         struct dcerpc_binding_handle *b;
9641         TALLOC_CTX *tmp_ctx;
9642
9643         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9644
9645         /* From MSDN documentation of SetPrinterDataEx: pass request to
9646            SetPrinterData if key is "PrinterDriverData" */
9647
9648         if (!Printer) {
9649                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9650                         OUR_HANDLE(r->in.handle)));
9651                 return WERR_BADFID;
9652         }
9653
9654         if (Printer->printer_type == SPLHND_SERVER) {
9655                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9656                         "Not implemented for server handles yet\n"));
9657                 return WERR_INVALID_PARAM;
9658         }
9659
9660         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9661                 return WERR_BADFID;
9662         }
9663
9664         /*
9665          * Access check : NT returns "access denied" if you make a
9666          * SetPrinterData call without the necessary privildge.
9667          * we were originally returning OK if nothing changed
9668          * which made Win2k issue **a lot** of SetPrinterData
9669          * when connecting to a printer  --jerry
9670          */
9671
9672         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9673                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9674                         "change denied by handle access permissions\n"));
9675                 return WERR_ACCESS_DENIED;
9676         }
9677
9678         tmp_ctx = talloc_new(p->mem_ctx);
9679         if (!tmp_ctx) {
9680                 return WERR_NOMEM;
9681         }
9682
9683         result = winreg_printer_binding_handle(tmp_ctx,
9684                                                get_session_info_system(),
9685                                                p->msg_ctx,
9686                                                &b);
9687         if (!W_ERROR_IS_OK(result)) {
9688                 goto done;
9689         }
9690
9691         result = winreg_get_printer(tmp_ctx, b,
9692                                     lp_servicename(talloc_tos(), snum),
9693                                     &pinfo2);
9694         if (!W_ERROR_IS_OK(result)) {
9695                 goto done;
9696         }
9697
9698         /* check for OID in valuename */
9699
9700         oid_string = strchr(r->in.value_name, ',');
9701         if (oid_string) {
9702                 *oid_string = '\0';
9703                 oid_string++;
9704         }
9705
9706         /* save the registry data */
9707
9708         result = winreg_set_printer_dataex(tmp_ctx, b,
9709                                            pinfo2->sharename,
9710                                            r->in.key_name,
9711                                            r->in.value_name,
9712                                            r->in.type,
9713                                            r->in.data,
9714                                            r->in.offered);
9715
9716         if (W_ERROR_IS_OK(result)) {
9717                 /* save the OID if one was specified */
9718                 if (oid_string) {
9719                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9720                                 r->in.key_name, SPOOL_OID_KEY);
9721                         if (!str) {
9722                                 result = WERR_NOMEM;
9723                                 goto done;
9724                         }
9725
9726                         /*
9727                          * I'm not checking the status here on purpose.  Don't know
9728                          * if this is right, but I'm returning the status from the
9729                          * previous set_printer_dataex() call.  I have no idea if
9730                          * this is right.    --jerry
9731                          */
9732                         winreg_set_printer_dataex(tmp_ctx, b,
9733                                                   pinfo2->sharename,
9734                                                   str,
9735                                                   r->in.value_name,
9736                                                   REG_SZ,
9737                                                   (uint8_t *) oid_string,
9738                                                   strlen(oid_string) + 1);
9739                 }
9740
9741                 result = winreg_printer_update_changeid(tmp_ctx, b,
9742                                                         lp_const_servicename(snum));
9743
9744         }
9745
9746 done:
9747         talloc_free(tmp_ctx);
9748         return result;
9749 }
9750
9751 /****************************************************************
9752  _spoolss_DeletePrinterDataEx
9753 ****************************************************************/
9754
9755 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9756                                     struct spoolss_DeletePrinterDataEx *r)
9757 {
9758         const char *printer;
9759         int             snum=0;
9760         WERROR          status = WERR_OK;
9761         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9762
9763         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9764
9765         if (!Printer) {
9766                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9767                         "Invalid handle (%s:%u:%u).\n",
9768                         OUR_HANDLE(r->in.handle)));
9769                 return WERR_BADFID;
9770         }
9771
9772         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9773                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9774                         "printer properties change denied by handle\n"));
9775                 return WERR_ACCESS_DENIED;
9776         }
9777
9778         if (!r->in.value_name || !r->in.key_name) {
9779                 return WERR_NOMEM;
9780         }
9781
9782         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9783                 return WERR_BADFID;
9784         }
9785         printer = lp_const_servicename(snum);
9786
9787         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9788                                               get_session_info_system(),
9789                                               p->msg_ctx,
9790                                               printer,
9791                                               r->in.key_name,
9792                                               r->in.value_name);
9793         if (W_ERROR_IS_OK(status)) {
9794                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9795                                                         get_session_info_system(),
9796                                                         p->msg_ctx,
9797                                                         printer);
9798         }
9799
9800         return status;
9801 }
9802
9803 /****************************************************************
9804  _spoolss_EnumPrinterKey
9805 ****************************************************************/
9806
9807 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9808                                struct spoolss_EnumPrinterKey *r)
9809 {
9810         uint32_t        num_keys;
9811         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9812         int             snum = 0;
9813         WERROR          result = WERR_BADFILE;
9814         const char **array = NULL;
9815         DATA_BLOB blob;
9816
9817         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9818
9819         if (!Printer) {
9820                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9821                         OUR_HANDLE(r->in.handle)));
9822                 return WERR_BADFID;
9823         }
9824
9825         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9826                 return WERR_BADFID;
9827         }
9828
9829         result = winreg_enum_printer_key_internal(p->mem_ctx,
9830                                          get_session_info_system(),
9831                                          p->msg_ctx,
9832                                          lp_const_servicename(snum),
9833                                          r->in.key_name,
9834                                          &num_keys,
9835                                          &array);
9836         if (!W_ERROR_IS_OK(result)) {
9837                 goto done;
9838         }
9839
9840         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9841                 result = WERR_NOMEM;
9842                 goto done;
9843         }
9844
9845         *r->out._ndr_size = r->in.offered / 2;
9846         *r->out.needed = blob.length;
9847
9848         if (r->in.offered < *r->out.needed) {
9849                 result = WERR_MORE_DATA;
9850         } else {
9851                 result = WERR_OK;
9852                 r->out.key_buffer->string_array = array;
9853         }
9854
9855  done:
9856         if (!W_ERROR_IS_OK(result)) {
9857                 TALLOC_FREE(array);
9858                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9859                         *r->out.needed = 0;
9860                 }
9861         }
9862
9863         return result;
9864 }
9865
9866 /****************************************************************
9867  _spoolss_DeletePrinterKey
9868 ****************************************************************/
9869
9870 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9871                                  struct spoolss_DeletePrinterKey *r)
9872 {
9873         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9874         int                     snum=0;
9875         WERROR                  status;
9876         const char *printer;
9877         struct dcerpc_binding_handle *b;
9878         TALLOC_CTX *tmp_ctx;
9879
9880         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9881
9882         if (!Printer) {
9883                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9884                         OUR_HANDLE(r->in.handle)));
9885                 return WERR_BADFID;
9886         }
9887
9888         /* if keyname == NULL, return error */
9889         if ( !r->in.key_name )
9890                 return WERR_INVALID_PARAM;
9891
9892         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9893                 return WERR_BADFID;
9894         }
9895
9896         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9897                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9898                         "printer properties change denied by handle\n"));
9899                 return WERR_ACCESS_DENIED;
9900         }
9901
9902         printer = lp_const_servicename(snum);
9903
9904         tmp_ctx = talloc_new(p->mem_ctx);
9905         if (!tmp_ctx) {
9906                 return WERR_NOMEM;
9907         }
9908
9909         status = winreg_printer_binding_handle(tmp_ctx,
9910                                                get_session_info_system(),
9911                                                p->msg_ctx,
9912                                                &b);
9913         if (!W_ERROR_IS_OK(status)) {
9914                 goto done;
9915         }
9916
9917         /* delete the key and all subkeys */
9918         status = winreg_delete_printer_key(tmp_ctx, b,
9919                                            printer,
9920                                            r->in.key_name);
9921         if (W_ERROR_IS_OK(status)) {
9922                 status = winreg_printer_update_changeid(tmp_ctx, b,
9923                                                         printer);
9924         }
9925
9926 done:
9927         talloc_free(tmp_ctx);
9928         return status;
9929 }
9930
9931 /****************************************************************
9932  _spoolss_EnumPrinterDataEx
9933 ****************************************************************/
9934
9935 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9936                                   struct spoolss_EnumPrinterDataEx *r)
9937 {
9938         uint32_t        count = 0;
9939         struct spoolss_PrinterEnumValues *info = NULL;
9940         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9941         int             snum;
9942         WERROR          result;
9943
9944         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9945
9946         *r->out.count = 0;
9947         *r->out.needed = 0;
9948         *r->out.info = NULL;
9949
9950         if (!Printer) {
9951                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9952                         OUR_HANDLE(r->in.handle)));
9953                 return WERR_BADFID;
9954         }
9955
9956         /*
9957          * first check for a keyname of NULL or "".  Win2k seems to send
9958          * this a lot and we should send back WERR_INVALID_PARAM
9959          * no need to spend time looking up the printer in this case.
9960          * --jerry
9961          */
9962
9963         if (!strlen(r->in.key_name)) {
9964                 result = WERR_INVALID_PARAM;
9965                 goto done;
9966         }
9967
9968         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9969                 return WERR_BADFID;
9970         }
9971
9972         /* now look for a match on the key name */
9973         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9974                                             get_session_info_system(),
9975                                             p->msg_ctx,
9976                                             lp_const_servicename(snum),
9977                                             r->in.key_name,
9978                                             &count,
9979                                             &info);
9980         if (!W_ERROR_IS_OK(result)) {
9981                 goto done;
9982         }
9983
9984 #if 0 /* FIXME - gd */
9985         /* housekeeping information in the reply */
9986
9987         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9988          * the hand marshalled container size is a multiple
9989          * of 4 bytes for RPC alignment.
9990          */
9991
9992         if (needed % 4) {
9993                 needed += 4-(needed % 4);
9994         }
9995 #endif
9996         *r->out.count   = count;
9997         *r->out.info    = info;
9998
9999  done:
10000         if (!W_ERROR_IS_OK(result)) {
10001                 return result;
10002         }
10003
10004         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10005                                                spoolss_EnumPrinterDataEx,
10006                                                *r->out.info,
10007                                                *r->out.count);
10008         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10009         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10010
10011         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10012 }
10013
10014 /****************************************************************************
10015 ****************************************************************************/
10016
10017 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10018                                                  const char *servername,
10019                                                  const char *environment,
10020                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
10021 {
10022         WERROR werr;
10023         char *path = NULL;
10024
10025         werr = compose_spoolss_server_path(mem_ctx,
10026                                            servername,
10027                                            environment,
10028                                            SPOOLSS_PRTPROCS_PATH,
10029                                            &path);
10030         if (!W_ERROR_IS_OK(werr)) {
10031                 return werr;
10032         }
10033
10034         DEBUG(4,("print processor directory: [%s]\n", path));
10035
10036         r->directory_name = path;
10037
10038         return WERR_OK;
10039 }
10040
10041 /****************************************************************
10042  _spoolss_GetPrintProcessorDirectory
10043 ****************************************************************/
10044
10045 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10046                                            struct spoolss_GetPrintProcessorDirectory *r)
10047 {
10048         WERROR result;
10049         char *prnproc_share = NULL;
10050         bool prnproc_share_exists = false;
10051         int snum;
10052
10053         /* that's an [in out] buffer */
10054
10055         if (!r->in.buffer && (r->in.offered != 0)) {
10056                 return WERR_INVALID_PARAM;
10057         }
10058
10059         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10060                 r->in.level));
10061
10062         *r->out.needed = 0;
10063
10064         /* r->in.level is ignored */
10065
10066         /* We always should reply with a local print processor directory so that
10067          * users are not forced to have a [prnproc$] share on the Samba spoolss
10068          * server, if users decide to do so, lets announce it though - Guenther */
10069
10070         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10071         if (!prnproc_share) {
10072                 return WERR_NOMEM;
10073         }
10074         if (snum != -1) {
10075                 prnproc_share_exists = true;
10076         }
10077
10078         result = getprintprocessordirectory_level_1(p->mem_ctx,
10079                                                     prnproc_share_exists ? r->in.server : NULL,
10080                                                     r->in.environment,
10081                                                     &r->out.info->info1);
10082         if (!W_ERROR_IS_OK(result)) {
10083                 TALLOC_FREE(r->out.info);
10084                 return result;
10085         }
10086
10087         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10088                                                                                    r->out.info, r->in.level);
10089         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10090
10091         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10092 }
10093
10094 /*******************************************************************
10095  ********************************************************************/
10096
10097 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10098                                const char *dllname)
10099 {
10100         enum ndr_err_code ndr_err;
10101         struct spoolss_MonitorUi ui;
10102
10103         ui.dll_name = dllname;
10104
10105         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10106                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10107         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10108                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10109         }
10110         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10111 }
10112
10113 /*******************************************************************
10114  Streams the monitor UI DLL name in UNICODE
10115 *******************************************************************/
10116
10117 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10118                                struct security_token *token, DATA_BLOB *in,
10119                                DATA_BLOB *out, uint32_t *needed)
10120 {
10121         const char *dllname = "tcpmonui.dll";
10122
10123         *needed = (strlen(dllname)+1) * 2;
10124
10125         if (out->length < *needed) {
10126                 return WERR_INSUFFICIENT_BUFFER;
10127         }
10128
10129         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10130                 return WERR_NOMEM;
10131         }
10132
10133         return WERR_OK;
10134 }
10135
10136 /*******************************************************************
10137  ********************************************************************/
10138
10139 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10140                              struct spoolss_PortData1 *port1,
10141                              const DATA_BLOB *buf)
10142 {
10143         enum ndr_err_code ndr_err;
10144         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10145                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10146         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10147                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10148         }
10149         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10150 }
10151
10152 /*******************************************************************
10153  ********************************************************************/
10154
10155 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10156                              struct spoolss_PortData2 *port2,
10157                              const DATA_BLOB *buf)
10158 {
10159         enum ndr_err_code ndr_err;
10160         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10161                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10162         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10163                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10164         }
10165         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10166 }
10167
10168 /*******************************************************************
10169  Create a new TCP/IP port
10170 *******************************************************************/
10171
10172 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10173                              struct security_token *token, DATA_BLOB *in,
10174                              DATA_BLOB *out, uint32_t *needed)
10175 {
10176         struct spoolss_PortData1 port1;
10177         struct spoolss_PortData2 port2;
10178         char *device_uri = NULL;
10179         uint32_t version;
10180
10181         const char *portname;
10182         const char *hostaddress;
10183         const char *queue;
10184         uint32_t port_number;
10185         uint32_t protocol;
10186
10187         /* peek for spoolss_PortData version */
10188
10189         if (!in || (in->length < (128 + 4))) {
10190                 return WERR_GENERAL_FAILURE;
10191         }
10192
10193         version = IVAL(in->data, 128);
10194
10195         switch (version) {
10196                 case 1:
10197                         ZERO_STRUCT(port1);
10198
10199                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10200                                 return WERR_NOMEM;
10201                         }
10202
10203                         portname        = port1.portname;
10204                         hostaddress     = port1.hostaddress;
10205                         queue           = port1.queue;
10206                         protocol        = port1.protocol;
10207                         port_number     = port1.port_number;
10208
10209                         break;
10210                 case 2:
10211                         ZERO_STRUCT(port2);
10212
10213                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10214                                 return WERR_NOMEM;
10215                         }
10216
10217                         portname        = port2.portname;
10218                         hostaddress     = port2.hostaddress;
10219                         queue           = port2.queue;
10220                         protocol        = port2.protocol;
10221                         port_number     = port2.port_number;
10222
10223                         break;
10224                 default:
10225                         DEBUG(1,("xcvtcp_addport: "
10226                                 "unknown version of port_data: %d\n", version));
10227                         return WERR_UNKNOWN_PORT;
10228         }
10229
10230         /* create the device URI and call the add_port_hook() */
10231
10232         switch (protocol) {
10233         case PROTOCOL_RAWTCP_TYPE:
10234                 device_uri = talloc_asprintf(mem_ctx,
10235                                 "socket://%s:%d/", hostaddress,
10236                                 port_number);
10237                 break;
10238
10239         case PROTOCOL_LPR_TYPE:
10240                 device_uri = talloc_asprintf(mem_ctx,
10241                         "lpr://%s/%s", hostaddress, queue );
10242                 break;
10243
10244         default:
10245                 return WERR_UNKNOWN_PORT;
10246         }
10247
10248         if (!device_uri) {
10249                 return WERR_NOMEM;
10250         }
10251
10252         return add_port_hook(mem_ctx, token, portname, device_uri);
10253 }
10254
10255 /*******************************************************************
10256 *******************************************************************/
10257
10258 struct xcv_api_table xcvtcp_cmds[] = {
10259         { "MonitorUI",  xcvtcp_monitorui },
10260         { "AddPort",    xcvtcp_addport},
10261         { NULL,         NULL }
10262 };
10263
10264 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10265                                      struct security_token *token, const char *command,
10266                                      DATA_BLOB *inbuf,
10267                                      DATA_BLOB *outbuf,
10268                                      uint32_t *needed )
10269 {
10270         int i;
10271
10272         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10273
10274         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10275                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10276                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10277         }
10278
10279         return WERR_BADFUNC;
10280 }
10281
10282 /*******************************************************************
10283 *******************************************************************/
10284 #if 0   /* don't support management using the "Local Port" monitor */
10285
10286 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10287                                  struct security_token *token, DATA_BLOB *in,
10288                                  DATA_BLOB *out, uint32_t *needed)
10289 {
10290         const char *dllname = "localui.dll";
10291
10292         *needed = (strlen(dllname)+1) * 2;
10293
10294         if (out->length < *needed) {
10295                 return WERR_INSUFFICIENT_BUFFER;
10296         }
10297
10298         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10299                 return WERR_NOMEM;
10300         }
10301
10302         return WERR_OK;
10303 }
10304
10305 /*******************************************************************
10306 *******************************************************************/
10307
10308 struct xcv_api_table xcvlocal_cmds[] = {
10309         { "MonitorUI",  xcvlocal_monitorui },
10310         { NULL,         NULL }
10311 };
10312 #else
10313 struct xcv_api_table xcvlocal_cmds[] = {
10314         { NULL,         NULL }
10315 };
10316 #endif
10317
10318
10319
10320 /*******************************************************************
10321 *******************************************************************/
10322
10323 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10324                                        struct security_token *token, const char *command,
10325                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10326                                        uint32_t *needed)
10327 {
10328         int i;
10329
10330         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10331
10332         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10333                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10334                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10335         }
10336         return WERR_BADFUNC;
10337 }
10338
10339 /****************************************************************
10340  _spoolss_XcvData
10341 ****************************************************************/
10342
10343 WERROR _spoolss_XcvData(struct pipes_struct *p,
10344                         struct spoolss_XcvData *r)
10345 {
10346         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10347         DATA_BLOB out_data = data_blob_null;
10348         WERROR werror;
10349
10350         if (!Printer) {
10351                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10352                         OUR_HANDLE(r->in.handle)));
10353                 return WERR_BADFID;
10354         }
10355
10356         /* Has to be a handle to the TCP/IP port monitor */
10357
10358         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10359                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10360                 return WERR_BADFID;
10361         }
10362
10363         /* requires administrative access to the server */
10364
10365         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10366                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10367                 return WERR_ACCESS_DENIED;
10368         }
10369
10370         /* Allocate the outgoing buffer */
10371
10372         if (r->in.out_data_size) {
10373                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10374                 if (out_data.data == NULL) {
10375                         return WERR_NOMEM;
10376                 }
10377         }
10378
10379         switch ( Printer->printer_type ) {
10380         case SPLHND_PORTMON_TCP:
10381                 werror = process_xcvtcp_command(p->mem_ctx,
10382                                                 p->session_info->security_token,
10383                                                 r->in.function_name,
10384                                                 &r->in.in_data, &out_data,
10385                                                 r->out.needed);
10386                 break;
10387         case SPLHND_PORTMON_LOCAL:
10388                 werror = process_xcvlocal_command(p->mem_ctx,
10389                                                   p->session_info->security_token,
10390                                                   r->in.function_name,
10391                                                   &r->in.in_data, &out_data,
10392                                                   r->out.needed);
10393                 break;
10394         default:
10395                 werror = WERR_INVALID_PRINT_MONITOR;
10396         }
10397
10398         if (!W_ERROR_IS_OK(werror)) {
10399                 return werror;
10400         }
10401
10402         *r->out.status_code = 0;
10403
10404         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10405                 memcpy(r->out.out_data, out_data.data,
10406                         MIN(r->in.out_data_size, out_data.length));
10407         }
10408
10409         return WERR_OK;
10410 }
10411
10412 /****************************************************************
10413  _spoolss_AddPrintProcessor
10414 ****************************************************************/
10415
10416 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10417                                   struct spoolss_AddPrintProcessor *r)
10418 {
10419         /* for now, just indicate success and ignore the add.  We'll
10420            automatically set the winprint processor for printer
10421            entries later.  Used to debug the LexMark Optra S 1855 PCL
10422            driver --jerry */
10423
10424         return WERR_OK;
10425 }
10426
10427 /****************************************************************
10428  _spoolss_AddPort
10429 ****************************************************************/
10430
10431 WERROR _spoolss_AddPort(struct pipes_struct *p,
10432                         struct spoolss_AddPort *r)
10433 {
10434         /* do what w2k3 does */
10435
10436         return WERR_NOT_SUPPORTED;
10437 }
10438
10439 /****************************************************************
10440  _spoolss_GetPrinterDriver
10441 ****************************************************************/
10442
10443 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10444                                  struct spoolss_GetPrinterDriver *r)
10445 {
10446         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10447         return WERR_NOT_SUPPORTED;
10448 }
10449
10450 /****************************************************************
10451  _spoolss_ReadPrinter
10452 ****************************************************************/
10453
10454 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10455                             struct spoolss_ReadPrinter *r)
10456 {
10457         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10458         return WERR_NOT_SUPPORTED;
10459 }
10460
10461 /****************************************************************
10462  _spoolss_WaitForPrinterChange
10463 ****************************************************************/
10464
10465 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10466                                      struct spoolss_WaitForPrinterChange *r)
10467 {
10468         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10469         return WERR_NOT_SUPPORTED;
10470 }
10471
10472 /****************************************************************
10473  _spoolss_ConfigurePort
10474 ****************************************************************/
10475
10476 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10477                               struct spoolss_ConfigurePort *r)
10478 {
10479         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10480         return WERR_NOT_SUPPORTED;
10481 }
10482
10483 /****************************************************************
10484  _spoolss_DeletePort
10485 ****************************************************************/
10486
10487 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10488                            struct spoolss_DeletePort *r)
10489 {
10490         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10491         return WERR_NOT_SUPPORTED;
10492 }
10493
10494 /****************************************************************
10495  _spoolss_CreatePrinterIC
10496 ****************************************************************/
10497
10498 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10499                                 struct spoolss_CreatePrinterIC *r)
10500 {
10501         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10502         return WERR_NOT_SUPPORTED;
10503 }
10504
10505 /****************************************************************
10506  _spoolss_PlayGDIScriptOnPrinterIC
10507 ****************************************************************/
10508
10509 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10510                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10511 {
10512         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10513         return WERR_NOT_SUPPORTED;
10514 }
10515
10516 /****************************************************************
10517  _spoolss_DeletePrinterIC
10518 ****************************************************************/
10519
10520 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10521                                 struct spoolss_DeletePrinterIC *r)
10522 {
10523         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10524         return WERR_NOT_SUPPORTED;
10525 }
10526
10527 /****************************************************************
10528  _spoolss_AddPrinterConnection
10529 ****************************************************************/
10530
10531 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10532                                      struct spoolss_AddPrinterConnection *r)
10533 {
10534         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10535         return WERR_NOT_SUPPORTED;
10536 }
10537
10538 /****************************************************************
10539  _spoolss_DeletePrinterConnection
10540 ****************************************************************/
10541
10542 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10543                                         struct spoolss_DeletePrinterConnection *r)
10544 {
10545         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10546         return WERR_NOT_SUPPORTED;
10547 }
10548
10549 /****************************************************************
10550  _spoolss_PrinterMessageBox
10551 ****************************************************************/
10552
10553 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10554                                   struct spoolss_PrinterMessageBox *r)
10555 {
10556         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10557         return WERR_NOT_SUPPORTED;
10558 }
10559
10560 /****************************************************************
10561  _spoolss_AddMonitor
10562 ****************************************************************/
10563
10564 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10565                            struct spoolss_AddMonitor *r)
10566 {
10567         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10568         return WERR_NOT_SUPPORTED;
10569 }
10570
10571 /****************************************************************
10572  _spoolss_DeleteMonitor
10573 ****************************************************************/
10574
10575 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10576                               struct spoolss_DeleteMonitor *r)
10577 {
10578         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10579         return WERR_NOT_SUPPORTED;
10580 }
10581
10582 /****************************************************************
10583  _spoolss_DeletePrintProcessor
10584 ****************************************************************/
10585
10586 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10587                                      struct spoolss_DeletePrintProcessor *r)
10588 {
10589         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10590         return WERR_NOT_SUPPORTED;
10591 }
10592
10593 /****************************************************************
10594  _spoolss_AddPrintProvidor
10595 ****************************************************************/
10596
10597 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10598                                  struct spoolss_AddPrintProvidor *r)
10599 {
10600         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10601         return WERR_NOT_SUPPORTED;
10602 }
10603
10604 /****************************************************************
10605  _spoolss_DeletePrintProvidor
10606 ****************************************************************/
10607
10608 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10609                                     struct spoolss_DeletePrintProvidor *r)
10610 {
10611         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10612         return WERR_NOT_SUPPORTED;
10613 }
10614
10615 /****************************************************************
10616  _spoolss_FindFirstPrinterChangeNotification
10617 ****************************************************************/
10618
10619 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10620                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10621 {
10622         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10623         return WERR_NOT_SUPPORTED;
10624 }
10625
10626 /****************************************************************
10627  _spoolss_FindNextPrinterChangeNotification
10628 ****************************************************************/
10629
10630 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10631                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10632 {
10633         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10634         return WERR_NOT_SUPPORTED;
10635 }
10636
10637 /****************************************************************
10638  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10639 ****************************************************************/
10640
10641 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10642                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10643 {
10644         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10645         return WERR_NOT_SUPPORTED;
10646 }
10647
10648 /****************************************************************
10649  _spoolss_ReplyOpenPrinter
10650 ****************************************************************/
10651
10652 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10653                                  struct spoolss_ReplyOpenPrinter *r)
10654 {
10655         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10656         return WERR_NOT_SUPPORTED;
10657 }
10658
10659 /****************************************************************
10660  _spoolss_RouterReplyPrinter
10661 ****************************************************************/
10662
10663 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10664                                    struct spoolss_RouterReplyPrinter *r)
10665 {
10666         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10667         return WERR_NOT_SUPPORTED;
10668 }
10669
10670 /****************************************************************
10671  _spoolss_ReplyClosePrinter
10672 ****************************************************************/
10673
10674 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10675                                   struct spoolss_ReplyClosePrinter *r)
10676 {
10677         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10678         return WERR_NOT_SUPPORTED;
10679 }
10680
10681 /****************************************************************
10682  _spoolss_AddPortEx
10683 ****************************************************************/
10684
10685 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10686                           struct spoolss_AddPortEx *r)
10687 {
10688         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10689         return WERR_NOT_SUPPORTED;
10690 }
10691
10692 /****************************************************************
10693  _spoolss_RouterFindFirstPrinterChangeNotification
10694 ****************************************************************/
10695
10696 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10697                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10698 {
10699         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10700         return WERR_NOT_SUPPORTED;
10701 }
10702
10703 /****************************************************************
10704  _spoolss_SpoolerInit
10705 ****************************************************************/
10706
10707 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10708                             struct spoolss_SpoolerInit *r)
10709 {
10710         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10711         return WERR_NOT_SUPPORTED;
10712 }
10713
10714 /****************************************************************
10715  _spoolss_ResetPrinterEx
10716 ****************************************************************/
10717
10718 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10719                                struct spoolss_ResetPrinterEx *r)
10720 {
10721         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10722         return WERR_NOT_SUPPORTED;
10723 }
10724
10725 /****************************************************************
10726  _spoolss_RouterReplyPrinterEx
10727 ****************************************************************/
10728
10729 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10730                                      struct spoolss_RouterReplyPrinterEx *r)
10731 {
10732         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10733         return WERR_NOT_SUPPORTED;
10734 }
10735
10736 /****************************************************************
10737  _spoolss_44
10738 ****************************************************************/
10739
10740 WERROR _spoolss_44(struct pipes_struct *p,
10741                    struct spoolss_44 *r)
10742 {
10743         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10744         return WERR_NOT_SUPPORTED;
10745 }
10746
10747 /****************************************************************
10748  _spoolss_SetPort
10749 ****************************************************************/
10750
10751 WERROR _spoolss_SetPort(struct pipes_struct *p,
10752                         struct spoolss_SetPort *r)
10753 {
10754         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10755         return WERR_NOT_SUPPORTED;
10756 }
10757
10758 /****************************************************************
10759  _spoolss_4a
10760 ****************************************************************/
10761
10762 WERROR _spoolss_4a(struct pipes_struct *p,
10763                    struct spoolss_4a *r)
10764 {
10765         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10766         return WERR_NOT_SUPPORTED;
10767 }
10768
10769 /****************************************************************
10770  _spoolss_4b
10771 ****************************************************************/
10772
10773 WERROR _spoolss_4b(struct pipes_struct *p,
10774                    struct spoolss_4b *r)
10775 {
10776         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10777         return WERR_NOT_SUPPORTED;
10778 }
10779
10780 /****************************************************************
10781  _spoolss_4c
10782 ****************************************************************/
10783
10784 WERROR _spoolss_4c(struct pipes_struct *p,
10785                    struct spoolss_4c *r)
10786 {
10787         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10788         return WERR_NOT_SUPPORTED;
10789 }
10790
10791 /****************************************************************
10792  _spoolss_53
10793 ****************************************************************/
10794
10795 WERROR _spoolss_53(struct pipes_struct *p,
10796                    struct spoolss_53 *r)
10797 {
10798         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10799         return WERR_NOT_SUPPORTED;
10800 }
10801
10802 /****************************************************************
10803  _spoolss_AddPerMachineConnection
10804 ****************************************************************/
10805
10806 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10807                                         struct spoolss_AddPerMachineConnection *r)
10808 {
10809         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10810         return WERR_NOT_SUPPORTED;
10811 }
10812
10813 /****************************************************************
10814  _spoolss_DeletePerMachineConnection
10815 ****************************************************************/
10816
10817 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10818                                            struct spoolss_DeletePerMachineConnection *r)
10819 {
10820         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10821         return WERR_NOT_SUPPORTED;
10822 }
10823
10824 /****************************************************************
10825  _spoolss_EnumPerMachineConnections
10826 ****************************************************************/
10827
10828 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10829                                           struct spoolss_EnumPerMachineConnections *r)
10830 {
10831         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10832         return WERR_NOT_SUPPORTED;
10833 }
10834
10835 /****************************************************************
10836  _spoolss_5a
10837 ****************************************************************/
10838
10839 WERROR _spoolss_5a(struct pipes_struct *p,
10840                    struct spoolss_5a *r)
10841 {
10842         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10843         return WERR_NOT_SUPPORTED;
10844 }
10845
10846 /****************************************************************
10847  _spoolss_5b
10848 ****************************************************************/
10849
10850 WERROR _spoolss_5b(struct pipes_struct *p,
10851                    struct spoolss_5b *r)
10852 {
10853         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10854         return WERR_NOT_SUPPORTED;
10855 }
10856
10857 /****************************************************************
10858  _spoolss_5c
10859 ****************************************************************/
10860
10861 WERROR _spoolss_5c(struct pipes_struct *p,
10862                    struct spoolss_5c *r)
10863 {
10864         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10865         return WERR_NOT_SUPPORTED;
10866 }
10867
10868 /****************************************************************
10869  _spoolss_5d
10870 ****************************************************************/
10871
10872 WERROR _spoolss_5d(struct pipes_struct *p,
10873                    struct spoolss_5d *r)
10874 {
10875         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10876         return WERR_NOT_SUPPORTED;
10877 }
10878
10879 /****************************************************************
10880  _spoolss_5e
10881 ****************************************************************/
10882
10883 WERROR _spoolss_5e(struct pipes_struct *p,
10884                    struct spoolss_5e *r)
10885 {
10886         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10887         return WERR_NOT_SUPPORTED;
10888 }
10889
10890 /****************************************************************
10891  _spoolss_5f
10892 ****************************************************************/
10893
10894 WERROR _spoolss_5f(struct pipes_struct *p,
10895                    struct spoolss_5f *r)
10896 {
10897         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10898         return WERR_NOT_SUPPORTED;
10899 }
10900
10901 /****************************************************************
10902  _spoolss_60
10903 ****************************************************************/
10904
10905 WERROR _spoolss_60(struct pipes_struct *p,
10906                    struct spoolss_60 *r)
10907 {
10908         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10909         return WERR_NOT_SUPPORTED;
10910 }
10911
10912 /****************************************************************
10913  _spoolss_RpcSendRecvBidiData
10914 ****************************************************************/
10915
10916 WERROR _spoolss_RpcSendRecvBidiData(struct pipes_struct *p,
10917                                     struct spoolss_RpcSendRecvBidiData *r)
10918 {
10919         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10920         return WERR_NOT_SUPPORTED;
10921 }
10922
10923 /****************************************************************
10924  _spoolss_62
10925 ****************************************************************/
10926
10927 WERROR _spoolss_62(struct pipes_struct *p,
10928                    struct spoolss_62 *r)
10929 {
10930         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10931         return WERR_NOT_SUPPORTED;
10932 }
10933
10934 /****************************************************************
10935  _spoolss_63
10936 ****************************************************************/
10937
10938 WERROR _spoolss_63(struct pipes_struct *p,
10939                    struct spoolss_63 *r)
10940 {
10941         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10942         return WERR_NOT_SUPPORTED;
10943 }
10944
10945 /****************************************************************
10946  _spoolss_64
10947 ****************************************************************/
10948
10949 WERROR _spoolss_64(struct pipes_struct *p,
10950                    struct spoolss_64 *r)
10951 {
10952         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10953         return WERR_NOT_SUPPORTED;
10954 }
10955
10956 /****************************************************************
10957  _spoolss_65
10958 ****************************************************************/
10959
10960 WERROR _spoolss_65(struct pipes_struct *p,
10961                    struct spoolss_65 *r)
10962 {
10963         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10964         return WERR_NOT_SUPPORTED;
10965 }
10966
10967 /****************************************************************
10968  _spoolss_GetCorePrinterDrivers
10969 ****************************************************************/
10970
10971 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10972                                       struct spoolss_GetCorePrinterDrivers *r)
10973 {
10974         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10975         return WERR_NOT_SUPPORTED;
10976 }
10977
10978 /****************************************************************
10979  _spoolss_67
10980 ****************************************************************/
10981
10982 WERROR _spoolss_67(struct pipes_struct *p,
10983                    struct spoolss_67 *r)
10984 {
10985         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10986         return WERR_NOT_SUPPORTED;
10987 }
10988
10989 /****************************************************************
10990  _spoolss_GetPrinterDriverPackagePath
10991 ****************************************************************/
10992
10993 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10994                                             struct spoolss_GetPrinterDriverPackagePath *r)
10995 {
10996         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10997         return WERR_NOT_SUPPORTED;
10998 }
10999
11000 /****************************************************************
11001  _spoolss_69
11002 ****************************************************************/
11003
11004 WERROR _spoolss_69(struct pipes_struct *p,
11005                    struct spoolss_69 *r)
11006 {
11007         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11008         return WERR_NOT_SUPPORTED;
11009 }
11010
11011 /****************************************************************
11012  _spoolss_6a
11013 ****************************************************************/
11014
11015 WERROR _spoolss_6a(struct pipes_struct *p,
11016                    struct spoolss_6a *r)
11017 {
11018         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11019         return WERR_NOT_SUPPORTED;
11020 }
11021
11022 /****************************************************************
11023  _spoolss_6b
11024 ****************************************************************/
11025
11026 WERROR _spoolss_6b(struct pipes_struct *p,
11027                    struct spoolss_6b *r)
11028 {
11029         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11030         return WERR_NOT_SUPPORTED;
11031 }
11032
11033 /****************************************************************
11034  _spoolss_6c
11035 ****************************************************************/
11036
11037 WERROR _spoolss_6c(struct pipes_struct *p,
11038                    struct spoolss_6c *r)
11039 {
11040         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11041         return WERR_NOT_SUPPORTED;
11042 }
11043
11044 /****************************************************************
11045  _spoolss_6d
11046 ****************************************************************/
11047
11048 WERROR _spoolss_6d(struct pipes_struct *p,
11049                    struct spoolss_6d *r)
11050 {
11051         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11052         return WERR_NOT_SUPPORTED;
11053 }
11054
11055 /****************************************************************
11056  _spoolss_RpcGetJobNamedPropertyValue
11057 ****************************************************************/
11058
11059 WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
11060                                             struct spoolss_RpcGetJobNamedPropertyValue *r)
11061 {
11062         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11063         return WERR_NOT_SUPPORTED;
11064 }
11065
11066 /****************************************************************
11067  _spoolss_RpcSetJobNamedProperty
11068 ****************************************************************/
11069
11070 WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
11071                                        struct spoolss_RpcSetJobNamedProperty *r)
11072 {
11073         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11074         return WERR_NOT_SUPPORTED;
11075 }
11076
11077 /****************************************************************
11078  _spoolss_RpcDeleteJobNamedProperty
11079 ****************************************************************/
11080
11081 WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
11082                                           struct spoolss_RpcDeleteJobNamedProperty *r)
11083 {
11084         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11085         return WERR_NOT_SUPPORTED;
11086 }
11087
11088 /****************************************************************
11089  _spoolss_RpcEnumJobNamedProperties
11090 ****************************************************************/
11091
11092 WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
11093                                           struct spoolss_RpcEnumJobNamedProperties *r)
11094 {
11095         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11096         return WERR_NOT_SUPPORTED;
11097 }