7413d9d4ccc2e353a1da484dd6bf3dac23b2376c
[metze/samba/wip.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
59
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62         ((info)?ndr_size_##fn(info, level, 0):0)
63
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
66
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
69
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71
72 #undef DBGC_CLASS
73 #define DBGC_CLASS DBGC_RPC_SRV
74
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
77 #endif
78
79 struct notify_back_channel;
80
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86         struct printer_handle *prev, *next;
87         bool document_started;
88         bool page_started;
89         uint32_t jobid; /* jobid in printing backend */
90         int printer_type;
91         const char *servername;
92         fstring sharename;
93         uint32_t type;
94         uint32_t access_granted;
95         struct {
96                 uint32_t flags;
97                 uint32_t options;
98                 fstring localmachine;
99                 uint32_t printerlocal;
100                 struct spoolss_NotifyOption *option;
101                 struct policy_handle cli_hnd;
102                 struct notify_back_channel *cli_chan;
103                 uint32_t 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         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
626         if (cache_key == NULL) {
627                 return WERR_NOMEM;
628         }
629
630         /*
631          * With hundreds of printers, the "for" loop iterating all
632          * shares can be quite expensive, as it is done on every
633          * OpenPrinter. The loop maps "aprinter" to "sname", the
634          * result of which we cache in gencache.
635          */
636         if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
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                 gencache_set(cache_key, printer_not_found,
707                              time_mono(NULL) + 300);
708                 TALLOC_FREE(cache_key);
709                 DEBUGADD(4,("Printer not found\n"));
710                 return WERR_INVALID_PRINTER_NAME;
711         }
712
713         gencache_set(cache_key, sname, time_mono(NULL) + 300);
714         TALLOC_FREE(cache_key);
715
716         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
717
718         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
719
720         return WERR_OK;
721 }
722
723 /****************************************************************************
724  Find first available printer slot. creates a printer handle for you.
725  ****************************************************************************/
726
727 static WERROR open_printer_hnd(struct pipes_struct *p,
728                                struct policy_handle *hnd,
729                                const char *name,
730                                uint32_t access_granted)
731 {
732         struct printer_handle *new_printer;
733         WERROR result;
734
735         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
736
737         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
738         if (new_printer == NULL) {
739                 return WERR_NOMEM;
740         }
741         talloc_set_destructor(new_printer, printer_entry_destructor);
742
743         /* This also steals the printer_handle on the policy_handle */
744         if (!create_policy_hnd(p, hnd, new_printer)) {
745                 TALLOC_FREE(new_printer);
746                 return WERR_INVALID_HANDLE;
747         }
748
749         /* Add to the internal list. */
750         DLIST_ADD(printers_list, new_printer);
751
752         new_printer->notify.option=NULL;
753
754         if (!set_printer_hnd_printertype(new_printer, name)) {
755                 close_printer_handle(p, hnd);
756                 return WERR_INVALID_HANDLE;
757         }
758
759         result = set_printer_hnd_name(p->mem_ctx,
760                                       get_session_info_system(),
761                                       p->msg_ctx,
762                                       new_printer, name);
763         if (!W_ERROR_IS_OK(result)) {
764                 close_printer_handle(p, hnd);
765                 return result;
766         }
767
768         new_printer->access_granted = access_granted;
769
770         DEBUG(5, ("%d printer handles active\n",
771                   (int)num_pipe_handles(p)));
772
773         return WERR_OK;
774 }
775
776 /***************************************************************************
777  check to see if the client motify handle is monitoring the notification
778  given by (notify_type, notify_field).
779  **************************************************************************/
780
781 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
782                                       uint16_t notify_field)
783 {
784         return true;
785 }
786
787 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
788                                 uint16_t notify_field)
789 {
790         struct spoolss_NotifyOption *option = p->notify.option;
791         uint32_t i, j;
792
793         /*
794          * Flags should always be zero when the change notify
795          * is registered by the client's spooler.  A user Win32 app
796          * might use the flags though instead of the NOTIFY_OPTION_INFO
797          * --jerry
798          */
799
800         if (!option) {
801                 return false;
802         }
803
804         if (p->notify.flags)
805                 return is_monitoring_event_flags(
806                         p->notify.flags, notify_type, notify_field);
807
808         for (i = 0; i < option->count; i++) {
809
810                 /* Check match for notify_type */
811
812                 if (option->types[i].type != notify_type)
813                         continue;
814
815                 /* Check match for field */
816
817                 for (j = 0; j < option->types[i].count; j++) {
818                         if (option->types[i].fields[j].field == notify_field) {
819                                 return true;
820                         }
821                 }
822         }
823
824         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
825                    p->servername, p->sharename, notify_type, notify_field));
826
827         return false;
828 }
829
830 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
831         _data->data.integer[0] = _integer; \
832         _data->data.integer[1] = 0;
833
834
835 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
836         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
837         if (!_data->data.string.string) {\
838                 _data->data.string.size = 0; \
839         } \
840         _data->data.string.size = strlen_m_term(_p) * 2;
841
842 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
843         _data->data.devmode.devmode = _devmode;
844
845 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
846                                    struct tm *t,
847                                    const char **pp,
848                                    uint32_t *plen)
849 {
850         struct spoolss_Time st;
851         uint32_t len = 16;
852         char *p;
853
854         if (!init_systemtime(&st, t)) {
855                 return;
856         }
857
858         p = talloc_array(mem_ctx, char, len);
859         if (!p) {
860                 return;
861         }
862
863         /*
864          * Systemtime must be linearized as a set of UINT16's.
865          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
866          */
867
868         SSVAL(p, 0, st.year);
869         SSVAL(p, 2, st.month);
870         SSVAL(p, 4, st.day_of_week);
871         SSVAL(p, 6, st.day);
872         SSVAL(p, 8, st.hour);
873         SSVAL(p, 10, st.minute);
874         SSVAL(p, 12, st.second);
875         SSVAL(p, 14, st.millisecond);
876
877         *pp = p;
878         *plen = len;
879 }
880
881 /* Convert a notification message to a struct spoolss_Notify */
882
883 static void notify_one_value(struct spoolss_notify_msg *msg,
884                              struct spoolss_Notify *data,
885                              TALLOC_CTX *mem_ctx)
886 {
887         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
888 }
889
890 static void notify_string(struct spoolss_notify_msg *msg,
891                           struct spoolss_Notify *data,
892                           TALLOC_CTX *mem_ctx)
893 {
894         /* The length of the message includes the trailing \0 */
895
896         data->data.string.size = msg->len * 2;
897         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
898         if (!data->data.string.string) {
899                 data->data.string.size = 0;
900                 return;
901         }
902 }
903
904 static void notify_system_time(struct spoolss_notify_msg *msg,
905                                struct spoolss_Notify *data,
906                                TALLOC_CTX *mem_ctx)
907 {
908         data->data.string.string = NULL;
909         data->data.string.size = 0;
910
911         if (msg->len != sizeof(time_t)) {
912                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
913                           msg->len));
914                 return;
915         }
916
917         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
918                                &data->data.string.string,
919                                &data->data.string.size);
920 }
921
922 struct notify2_message_table {
923         const char *name;
924         void (*fn)(struct spoolss_notify_msg *msg,
925                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
926 };
927
928 static struct notify2_message_table printer_notify_table[] = {
929         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
930         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
931         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
932         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
933         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
934         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
935         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
936         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
937         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
938         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
939         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
940         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
941         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
942         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
943         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
944         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
945         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
946         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
947         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
948 };
949
950 static struct notify2_message_table job_notify_table[] = {
951         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
952         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
953         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
954         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
955         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
956         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
957         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
958         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
959         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
960         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
961         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
962         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
963         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
964         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
965         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
966         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
967         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
968         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
969         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
970         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
971         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
972         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
973         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
974         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
975 };
976
977
978 /***********************************************************************
979  Allocate talloc context for container object
980  **********************************************************************/
981
982 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
983 {
984         if ( !ctr )
985                 return;
986
987         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
988
989         return;
990 }
991
992 /***********************************************************************
993  release all allocated memory and zero out structure
994  **********************************************************************/
995
996 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
997 {
998         if ( !ctr )
999                 return;
1000
1001         if ( ctr->ctx )
1002                 talloc_destroy(ctr->ctx);
1003
1004         ZERO_STRUCTP(ctr);
1005
1006         return;
1007 }
1008
1009 /***********************************************************************
1010  **********************************************************************/
1011
1012 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1013 {
1014         if ( !ctr )
1015                 return NULL;
1016
1017         return ctr->ctx;
1018 }
1019
1020 /***********************************************************************
1021  **********************************************************************/
1022
1023 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1024 {
1025         if ( !ctr || !ctr->msg_groups )
1026                 return NULL;
1027
1028         if ( idx >= ctr->num_groups )
1029                 return NULL;
1030
1031         return &ctr->msg_groups[idx];
1032
1033 }
1034
1035 /***********************************************************************
1036  How many groups of change messages do we have ?
1037  **********************************************************************/
1038
1039 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1040 {
1041         if ( !ctr )
1042                 return 0;
1043
1044         return ctr->num_groups;
1045 }
1046
1047 /***********************************************************************
1048  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1049  **********************************************************************/
1050
1051 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1052 {
1053         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1054         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1055         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1056         int                             i, new_slot;
1057
1058         if ( !ctr || !msg )
1059                 return 0;
1060
1061         /* loop over all groups looking for a matching printer name */
1062
1063         for ( i=0; i<ctr->num_groups; i++ ) {
1064                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1065                         break;
1066         }
1067
1068         /* add a new group? */
1069
1070         if ( i == ctr->num_groups ) {
1071                 ctr->num_groups++;
1072
1073                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1074                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1075                         return 0;
1076                 }
1077                 ctr->msg_groups = groups;
1078
1079                 /* clear the new entry and set the printer name */
1080
1081                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1082                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1083         }
1084
1085         /* add the change messages; 'i' is the correct index now regardless */
1086
1087         msg_grp = &ctr->msg_groups[i];
1088
1089         msg_grp->num_msgs++;
1090
1091         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1092                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1093                 return 0;
1094         }
1095         msg_grp->msgs = msg_list;
1096
1097         new_slot = msg_grp->num_msgs-1;
1098         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1099
1100         /* need to allocate own copy of data */
1101
1102         if ( msg->len != 0 )
1103                 msg_grp->msgs[new_slot].notify.data = (char *)
1104                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1105
1106         return ctr->num_groups;
1107 }
1108
1109 static void construct_info_data(struct spoolss_Notify *info_data,
1110                                 enum spoolss_NotifyType type,
1111                                 uint16_t field, int id);
1112
1113 /***********************************************************************
1114  Send a change notication message on all handles which have a call
1115  back registered
1116  **********************************************************************/
1117
1118 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1119                                   struct printer_handle *prn_hnd,
1120                                   SPOOLSS_NOTIFY_MSG *messages,
1121                                   uint32_t num_msgs,
1122                                   struct spoolss_Notify **_notifies,
1123                                   int *_count)
1124 {
1125         struct spoolss_Notify *notifies;
1126         SPOOLSS_NOTIFY_MSG *msg;
1127         int count = 0;
1128         uint32_t id;
1129         int i;
1130
1131         notifies = talloc_zero_array(mem_ctx,
1132                                      struct spoolss_Notify, num_msgs);
1133         if (!notifies) {
1134                 return ENOMEM;
1135         }
1136
1137         for (i = 0; i < num_msgs; i++) {
1138
1139                 msg = &messages[i];
1140
1141                 /* Are we monitoring this event? */
1142
1143                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1144                         continue;
1145                 }
1146
1147                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1148                            "for printer [%s]\n",
1149                            msg->type, msg->field, prn_hnd->sharename));
1150
1151                 /*
1152                  * if the is a printer notification handle and not a job
1153                  * notification type, then set the id to 0.
1154                  * Otherwise just use what was specified in the message.
1155                  *
1156                  * When registering change notification on a print server
1157                  * handle we always need to send back the id (snum) matching
1158                  * the printer for which the change took place.
1159                  * For change notify registered on a printer handle,
1160                  * this does not matter and the id should be 0.
1161                  *
1162                  * --jerry
1163                  */
1164
1165                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1166                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1167                         id = 0;
1168                 } else {
1169                         id = msg->id;
1170                 }
1171
1172                 /* Convert unix jobid to smb jobid */
1173
1174                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1175                         id = sysjob_to_jobid(msg->id);
1176
1177                         if (id == -1) {
1178                                 DEBUG(3, ("no such unix jobid %d\n",
1179                                           msg->id));
1180                                 continue;
1181                         }
1182                 }
1183
1184                 construct_info_data(&notifies[count],
1185                                     msg->type, msg->field, id);
1186
1187                 switch(msg->type) {
1188                 case PRINTER_NOTIFY_TYPE:
1189                         if (printer_notify_table[msg->field].fn) {
1190                                 printer_notify_table[msg->field].fn(msg,
1191                                                 &notifies[count], mem_ctx);
1192                         }
1193                         break;
1194
1195                 case JOB_NOTIFY_TYPE:
1196                         if (job_notify_table[msg->field].fn) {
1197                                 job_notify_table[msg->field].fn(msg,
1198                                                 &notifies[count], mem_ctx);
1199                         }
1200                         break;
1201
1202                 default:
1203                         DEBUG(5, ("Unknown notification type %d\n",
1204                                   msg->type));
1205                         continue;
1206                 }
1207
1208                 count++;
1209         }
1210
1211         *_notifies = notifies;
1212         *_count = count;
1213
1214         return 0;
1215 }
1216
1217 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1218                                 struct printer_handle *prn_hnd,
1219                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1220 {
1221         struct spoolss_Notify *notifies;
1222         int count = 0;
1223         union spoolss_ReplyPrinterInfo info;
1224         struct spoolss_NotifyInfo info0;
1225         uint32_t reply_result;
1226         NTSTATUS status;
1227         WERROR werr;
1228         int ret;
1229
1230         /* Is there notification on this handle? */
1231         if (prn_hnd->notify.cli_chan == NULL ||
1232             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1233             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1234             prn_hnd->notify.cli_chan->active_connections == 0) {
1235                 return 0;
1236         }
1237
1238         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1239                    prn_hnd->servername, prn_hnd->sharename));
1240
1241         /* For this printer? Print servers always receive notifications. */
1242         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1243             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1244                 return 0;
1245         }
1246
1247         DEBUG(10,("Our printer\n"));
1248
1249         /* build the array of change notifications */
1250         ret = build_notify2_messages(mem_ctx, prn_hnd,
1251                                      msg_group->msgs,
1252                                      msg_group->num_msgs,
1253                                      &notifies, &count);
1254         if (ret) {
1255                 return ret;
1256         }
1257
1258         info0.version   = 0x2;
1259         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1260         info0.count     = count;
1261         info0.notifies  = notifies;
1262
1263         info.info0 = &info0;
1264
1265         status = dcerpc_spoolss_RouterReplyPrinterEx(
1266                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1267                                 mem_ctx,
1268                                 &prn_hnd->notify.cli_hnd,
1269                                 prn_hnd->notify.change, /* color */
1270                                 prn_hnd->notify.flags,
1271                                 &reply_result,
1272                                 0, /* reply_type, must be 0 */
1273                                 info, &werr);
1274         if (!NT_STATUS_IS_OK(status)) {
1275                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1276                           "failed: %s\n",
1277                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1278                           nt_errstr(status)));
1279                 werr = ntstatus_to_werror(status);
1280         } else if (!W_ERROR_IS_OK(werr)) {
1281                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1282                           "failed: %s\n",
1283                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1284                           win_errstr(werr)));
1285         }
1286         switch (reply_result) {
1287         case 0:
1288                 break;
1289         case PRINTER_NOTIFY_INFO_DISCARDED:
1290         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1291         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1292                 break;
1293         default:
1294                 break;
1295         }
1296
1297         return 0;
1298 }
1299
1300 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1301 {
1302         struct printer_handle    *p;
1303         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1304         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1305         int ret;
1306
1307         if ( !msg_group ) {
1308                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1309                 return;
1310         }
1311
1312         if (!msg_group->msgs) {
1313                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1314                 return;
1315         }
1316
1317         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1318
1319         /* loop over all printers */
1320
1321         for (p = printers_list; p; p = p->next) {
1322                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1323                 if (ret) {
1324                         goto done;
1325                 }
1326         }
1327
1328 done:
1329         DEBUG(8,("send_notify2_changes: Exit...\n"));
1330         return;
1331 }
1332
1333 /***********************************************************************
1334  **********************************************************************/
1335
1336 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1337 {
1338
1339         uint32_t tv_sec, tv_usec;
1340         size_t offset = 0;
1341
1342         /* Unpack message */
1343
1344         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1345                              msg->printer);
1346
1347         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1348                                 &tv_sec, &tv_usec,
1349                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1350
1351         if (msg->len == 0)
1352                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1353                            &msg->notify.value[0], &msg->notify.value[1]);
1354         else
1355                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1356                            &msg->len, &msg->notify.data);
1357
1358         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1359                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1360
1361         tv->tv_sec = tv_sec;
1362         tv->tv_usec = tv_usec;
1363
1364         if (msg->len == 0)
1365                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1366                           msg->notify.value[1]));
1367         else
1368                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1369
1370         return true;
1371 }
1372
1373 /********************************************************************
1374  Receive a notify2 message list
1375  ********************************************************************/
1376
1377 static void receive_notify2_message_list(struct messaging_context *msg,
1378                                          void *private_data,
1379                                          uint32_t msg_type,
1380                                          struct server_id server_id,
1381                                          DATA_BLOB *data)
1382 {
1383         size_t                  msg_count, i;
1384         char                    *buf = (char *)data->data;
1385         char                    *msg_ptr;
1386         size_t                  msg_len;
1387         SPOOLSS_NOTIFY_MSG      notify;
1388         SPOOLSS_NOTIFY_MSG_CTR  messages;
1389         int                     num_groups;
1390
1391         if (data->length < 4) {
1392                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1393                 return;
1394         }
1395
1396         msg_count = IVAL(buf, 0);
1397         msg_ptr = buf + 4;
1398
1399         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1400
1401         if (msg_count == 0) {
1402                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1403                 return;
1404         }
1405
1406         /* initialize the container */
1407
1408         ZERO_STRUCT( messages );
1409         notify_msg_ctr_init( &messages );
1410
1411         /*
1412          * build message groups for each printer identified
1413          * in a change_notify msg.  Remember that a PCN message
1414          * includes the handle returned for the srv_spoolss_replyopenprinter()
1415          * call.  Therefore messages are grouped according to printer handle.
1416          */
1417
1418         for ( i=0; i<msg_count; i++ ) {
1419                 struct timeval msg_tv;
1420
1421                 if (msg_ptr + 4 - buf > data->length) {
1422                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1423                         return;
1424                 }
1425
1426                 msg_len = IVAL(msg_ptr,0);
1427                 msg_ptr += 4;
1428
1429                 if (msg_ptr + msg_len - buf > data->length) {
1430                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1431                         return;
1432                 }
1433
1434                 /* unpack messages */
1435
1436                 ZERO_STRUCT( notify );
1437                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1438                 msg_ptr += msg_len;
1439
1440                 /* add to correct list in container */
1441
1442                 notify_msg_ctr_addmsg( &messages, &notify );
1443
1444                 /* free memory that might have been allocated by notify2_unpack_msg() */
1445
1446                 if ( notify.len != 0 )
1447                         SAFE_FREE( notify.notify.data );
1448         }
1449
1450         /* process each group of messages */
1451
1452         num_groups = notify_msg_ctr_numgroups( &messages );
1453         for ( i=0; i<num_groups; i++ )
1454                 send_notify2_changes( &messages, i );
1455
1456
1457         /* cleanup */
1458
1459         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1460                 (uint32_t)msg_count ));
1461
1462         notify_msg_ctr_destroy( &messages );
1463
1464         return;
1465 }
1466
1467 /********************************************************************
1468  Send a message to ourself about new driver being installed
1469  so we can upgrade the information for each printer bound to this
1470  driver
1471  ********************************************************************/
1472
1473 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1474                                             struct messaging_context *msg_ctx)
1475 {
1476         int len = strlen(drivername);
1477
1478         if (!len)
1479                 return false;
1480
1481         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1482                 drivername));
1483
1484         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1485                            MSG_PRINTER_DRVUPGRADE,
1486                            (const uint8_t *)drivername, len+1);
1487
1488         return true;
1489 }
1490
1491 void srv_spoolss_cleanup(void)
1492 {
1493         struct printer_session_counter *session_counter;
1494
1495         for (session_counter = counter_list;
1496              session_counter != NULL;
1497              session_counter = counter_list) {
1498                 DLIST_REMOVE(counter_list, session_counter);
1499                 TALLOC_FREE(session_counter);
1500         }
1501 }
1502
1503 /**********************************************************************
1504  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1505  over all printers, upgrading ones as necessary
1506  This is now *ONLY* called inside the background lpq updater. JRA.
1507  **********************************************************************/
1508
1509 void do_drv_upgrade_printer(struct messaging_context *msg,
1510                             void *private_data,
1511                             uint32_t msg_type,
1512                             struct server_id server_id,
1513                             DATA_BLOB *data)
1514 {
1515         TALLOC_CTX *tmp_ctx;
1516         const struct auth_session_info *session_info = get_session_info_system();
1517         struct spoolss_PrinterInfo2 *pinfo2;
1518         WERROR result;
1519         const char *drivername;
1520         int snum;
1521         int n_services = lp_numservices();
1522         struct dcerpc_binding_handle *b = NULL;
1523
1524         tmp_ctx = talloc_new(NULL);
1525         if (!tmp_ctx) return;
1526
1527         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1528         if (!drivername) {
1529                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1530                 goto done;
1531         }
1532
1533         DEBUG(10, ("do_drv_upgrade_printer: "
1534                    "Got message for new driver [%s]\n", drivername));
1535
1536         /* Iterate the printer list */
1537
1538         for (snum = 0; snum < n_services; snum++) {
1539                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1540                         continue;
1541                 }
1542
1543                 /* ignore [printers] share */
1544                 if (strequal(lp_const_servicename(snum), "printers")) {
1545                         continue;
1546                 }
1547
1548                 if (b == NULL) {
1549                         result = winreg_printer_binding_handle(tmp_ctx,
1550                                                                session_info,
1551                                                                msg,
1552                                                                &b);
1553                         if (!W_ERROR_IS_OK(result)) {
1554                                 break;
1555                         }
1556                 }
1557
1558                 result = winreg_get_printer(tmp_ctx, b,
1559                                             lp_const_servicename(snum),
1560                                             &pinfo2);
1561
1562                 if (!W_ERROR_IS_OK(result)) {
1563                         continue;
1564                 }
1565
1566                 if (!pinfo2->drivername) {
1567                         continue;
1568                 }
1569
1570                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1571                         continue;
1572                 }
1573
1574                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1575
1576                 /* all we care about currently is the change_id */
1577                 result = winreg_printer_update_changeid(tmp_ctx, b,
1578                                                         pinfo2->printername);
1579
1580                 if (!W_ERROR_IS_OK(result)) {
1581                         DEBUG(3, ("do_drv_upgrade_printer: "
1582                                   "Failed to update changeid [%s]\n",
1583                                   win_errstr(result)));
1584                 }
1585         }
1586
1587         /* all done */
1588 done:
1589         talloc_free(tmp_ctx);
1590 }
1591
1592 /********************************************************************
1593  Update the cache for all printq's with a registered client
1594  connection
1595  ********************************************************************/
1596
1597 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1598 {
1599         struct printer_handle *printer = printers_list;
1600         int snum;
1601
1602         /* loop through all printers and update the cache where
1603            a client is connected */
1604         while (printer) {
1605                 if ((printer->printer_type == SPLHND_PRINTER) &&
1606                     ((printer->notify.cli_chan != NULL) &&
1607                      (printer->notify.cli_chan->active_connections > 0))) {
1608                         snum = print_queue_snum(printer->sharename);
1609                         print_queue_status(msg_ctx, snum, NULL, NULL);
1610                 }
1611
1612                 printer = printer->next;
1613         }
1614
1615         return;
1616 }
1617
1618 /****************************************************************
1619  _spoolss_OpenPrinter
1620 ****************************************************************/
1621
1622 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1623                             struct spoolss_OpenPrinter *r)
1624 {
1625         struct spoolss_OpenPrinterEx e;
1626         struct spoolss_UserLevel1 level1;
1627         WERROR werr;
1628
1629         ZERO_STRUCT(level1);
1630
1631         e.in.printername        = r->in.printername;
1632         e.in.datatype           = r->in.datatype;
1633         e.in.devmode_ctr        = r->in.devmode_ctr;
1634         e.in.access_mask        = r->in.access_mask;
1635         e.in.userlevel_ctr.level                = 1;
1636         e.in.userlevel_ctr.user_info.level1     = &level1;
1637
1638         e.out.handle            = r->out.handle;
1639
1640         werr = _spoolss_OpenPrinterEx(p, &e);
1641
1642         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1643                 /* OpenPrinterEx returns this for a bad
1644                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1645                  * instead.
1646                  */
1647                 werr = WERR_INVALID_PRINTER_NAME;
1648         }
1649
1650         return werr;
1651 }
1652
1653 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1654                               struct spoolss_DeviceMode *orig,
1655                               struct spoolss_DeviceMode **dest)
1656 {
1657         struct spoolss_DeviceMode *dm;
1658
1659         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1660         if (!dm) {
1661                 return WERR_NOMEM;
1662         }
1663
1664         /* copy all values, then duplicate strings and structs */
1665         *dm = *orig;
1666
1667         dm->devicename = talloc_strdup(dm, orig->devicename);
1668         if (!dm->devicename) {
1669                 return WERR_NOMEM;
1670         }
1671         dm->formname = talloc_strdup(dm, orig->formname);
1672         if (!dm->formname) {
1673                 return WERR_NOMEM;
1674         }
1675         if (orig->driverextra_data.data) {
1676                 dm->driverextra_data.data =
1677                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1678                                         orig->driverextra_data.length);
1679                 if (!dm->driverextra_data.data) {
1680                         return WERR_NOMEM;
1681                 }
1682         }
1683
1684         *dest = dm;
1685         return WERR_OK;
1686 }
1687
1688 /****************************************************************
1689  _spoolss_OpenPrinterEx
1690 ****************************************************************/
1691
1692 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1693                               struct spoolss_OpenPrinterEx *r)
1694 {
1695         int snum;
1696         char *raddr;
1697         char *rhost;
1698         struct printer_handle *Printer=NULL;
1699         WERROR result;
1700         int rc;
1701
1702         if (!r->in.printername) {
1703                 return WERR_INVALID_PARAM;
1704         }
1705
1706         if (!*r->in.printername) {
1707                 return WERR_INVALID_PARAM;
1708         }
1709
1710         if (r->in.userlevel_ctr.level > 3) {
1711                 return WERR_INVALID_PARAM;
1712         }
1713         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1714             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1715             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1716                 return WERR_INVALID_PARAM;
1717         }
1718
1719         /*
1720          * The printcap printer share inventory is updated on client
1721          * enumeration. For clients that do not perform enumeration prior to
1722          * access, such as cupssmbadd, we reinitialise the printer share
1723          * inventory on open as well.
1724          */
1725         become_root();
1726         delete_and_reload_printers(server_event_context(), p->msg_ctx);
1727         unbecome_root();
1728
1729         /* some sanity check because you can open a printer or a print server */
1730         /* aka: \\server\printer or \\server */
1731
1732         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1733
1734         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1735         if (!W_ERROR_IS_OK(result)) {
1736                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1737                         "for printer %s\n", r->in.printername));
1738                 ZERO_STRUCTP(r->out.handle);
1739                 return result;
1740         }
1741
1742         Printer = find_printer_index_by_hnd(p, r->out.handle);
1743         if ( !Printer ) {
1744                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1745                         "handle we created for printer %s\n", r->in.printername));
1746                 close_printer_handle(p, r->out.handle);
1747                 ZERO_STRUCTP(r->out.handle);
1748                 return WERR_INVALID_PARAM;
1749         }
1750
1751         /*
1752          * First case: the user is opening the print server:
1753          *
1754          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1755          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1756          *
1757          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1758          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1759          * or if the user is listed in the smb.conf printer admin parameter.
1760          *
1761          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1762          * client view printer folder, but does not show the MSAPW.
1763          *
1764          * Note: this test needs code to check access rights here too. Jeremy
1765          * could you look at this?
1766          *
1767          * Second case: the user is opening a printer:
1768          * NT doesn't let us connect to a printer if the connecting user
1769          * doesn't have print permission.
1770          *
1771          * Third case: user is opening a Port Monitor
1772          * access checks same as opening a handle to the print server.
1773          */
1774
1775         switch (Printer->printer_type )
1776         {
1777         case SPLHND_SERVER:
1778         case SPLHND_PORTMON_TCP:
1779         case SPLHND_PORTMON_LOCAL:
1780                 /* Printserver handles use global struct... */
1781
1782                 snum = -1;
1783
1784                 /* Map standard access rights to object specific access rights */
1785
1786                 se_map_standard(&r->in.access_mask,
1787                                 &printserver_std_mapping);
1788
1789                 /* Deny any object specific bits that don't apply to print
1790                    servers (i.e printer and job specific bits) */
1791
1792                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1793
1794                 if (r->in.access_mask &
1795                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1796                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1797                         close_printer_handle(p, r->out.handle);
1798                         ZERO_STRUCTP(r->out.handle);
1799                         return WERR_ACCESS_DENIED;
1800                 }
1801
1802                 /* Allow admin access */
1803
1804                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1805                 {
1806                         if (!lp_show_add_printer_wizard()) {
1807                                 close_printer_handle(p, r->out.handle);
1808                                 ZERO_STRUCTP(r->out.handle);
1809                                 return WERR_ACCESS_DENIED;
1810                         }
1811
1812                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1813                            and not a printer admin, then fail */
1814
1815                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1816                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1817                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1818                                                 p->session_info->security_token)) {
1819                                 close_printer_handle(p, r->out.handle);
1820                                 ZERO_STRUCTP(r->out.handle);
1821                                 DEBUG(3,("access DENIED as user is not root, "
1822                                         "has no printoperator privilege, "
1823                                         "not a member of the printoperator builtin group and "
1824                                         "is not in printer admin list"));
1825                                 return WERR_ACCESS_DENIED;
1826                         }
1827
1828                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1829                 }
1830                 else
1831                 {
1832                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1833                 }
1834
1835                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1836                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1837
1838                 /* We fall through to return WERR_OK */
1839                 break;
1840
1841         case SPLHND_PRINTER:
1842                 /* NT doesn't let us connect to a printer if the connecting user
1843                    doesn't have print permission.  */
1844
1845                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1846                         close_printer_handle(p, r->out.handle);
1847                         ZERO_STRUCTP(r->out.handle);
1848                         return WERR_BADFID;
1849                 }
1850
1851                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1852                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1853                 }
1854
1855                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1856
1857                 /* map an empty access mask to the minimum access mask */
1858                 if (r->in.access_mask == 0x0)
1859                         r->in.access_mask = PRINTER_ACCESS_USE;
1860
1861                 /*
1862                  * If we are not serving the printer driver for this printer,
1863                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1864                  * will keep NT clients happy  --jerry
1865                  */
1866
1867                 if (lp_use_client_driver(snum)
1868                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1869                 {
1870                         r->in.access_mask = PRINTER_ACCESS_USE;
1871                 }
1872
1873                 /* check smb.conf parameters and the the sec_desc */
1874                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1875                                                          p->mem_ctx);
1876                 if (raddr == NULL) {
1877                         return WERR_NOMEM;
1878                 }
1879
1880                 rc = get_remote_hostname(p->remote_address,
1881                                          &rhost,
1882                                          p->mem_ctx);
1883                 if (rc < 0) {
1884                         return WERR_NOMEM;
1885                 }
1886                 if (strequal(rhost, "UNKNOWN")) {
1887                         rhost = raddr;
1888                 }
1889
1890                 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1891                                   rhost, raddr)) {
1892                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1893                         ZERO_STRUCTP(r->out.handle);
1894                         return WERR_ACCESS_DENIED;
1895                 }
1896
1897                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1898                                    p->session_info->security_token, snum) ||
1899                     !W_ERROR_IS_OK(print_access_check(p->session_info,
1900                                                       p->msg_ctx,
1901                                                       snum,
1902                                                       r->in.access_mask))) {
1903                         DEBUG(3, ("access DENIED for printer open\n"));
1904                         close_printer_handle(p, r->out.handle);
1905                         ZERO_STRUCTP(r->out.handle);
1906                         return WERR_ACCESS_DENIED;
1907                 }
1908
1909                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1910                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1911                         close_printer_handle(p, r->out.handle);
1912                         ZERO_STRUCTP(r->out.handle);
1913                         return WERR_ACCESS_DENIED;
1914                 }
1915
1916                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1917                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1918                 else
1919                         r->in.access_mask = PRINTER_ACCESS_USE;
1920
1921                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1922                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1923
1924                 winreg_create_printer_internal(p->mem_ctx,
1925                                       get_session_info_system(),
1926                                       p->msg_ctx,
1927                                       lp_const_servicename(snum));
1928
1929                 break;
1930
1931         default:
1932                 /* sanity check to prevent programmer error */
1933                 ZERO_STRUCTP(r->out.handle);
1934                 return WERR_BADFID;
1935         }
1936
1937         Printer->access_granted = r->in.access_mask;
1938
1939         /*
1940          * If the client sent a devmode in the OpenPrinter() call, then
1941          * save it here in case we get a job submission on this handle
1942          */
1943
1944          if ((Printer->printer_type != SPLHND_SERVER)
1945           && (r->in.devmode_ctr.devmode != NULL)) {
1946                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1947                                 &Printer->devmode);
1948          }
1949
1950         return WERR_OK;
1951 }
1952
1953 /****************************************************************
1954  _spoolss_ClosePrinter
1955 ****************************************************************/
1956
1957 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1958                              struct spoolss_ClosePrinter *r)
1959 {
1960         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1961
1962         if (Printer && Printer->document_started) {
1963                 struct spoolss_EndDocPrinter e;
1964
1965                 e.in.handle = r->in.handle;
1966
1967                 _spoolss_EndDocPrinter(p, &e);
1968         }
1969
1970         if (!close_printer_handle(p, r->in.handle))
1971                 return WERR_BADFID;
1972
1973         /* clear the returned printer handle.  Observed behavior
1974            from Win2k server.  Don't think this really matters.
1975            Previous code just copied the value of the closed
1976            handle.    --jerry */
1977
1978         ZERO_STRUCTP(r->out.handle);
1979
1980         return WERR_OK;
1981 }
1982
1983 /****************************************************************
1984  _spoolss_DeletePrinter
1985 ****************************************************************/
1986
1987 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1988                               struct spoolss_DeletePrinter *r)
1989 {
1990         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1991         WERROR result;
1992         int snum;
1993
1994         if (Printer && Printer->document_started) {
1995                 struct spoolss_EndDocPrinter e;
1996
1997                 e.in.handle = r->in.handle;
1998
1999                 _spoolss_EndDocPrinter(p, &e);
2000         }
2001
2002         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2003                 winreg_delete_printer_key_internal(p->mem_ctx,
2004                                           get_session_info_system(),
2005                                           p->msg_ctx,
2006                                           lp_const_servicename(snum),
2007                                           "");
2008         }
2009
2010         result = delete_printer_handle(p, r->in.handle);
2011
2012         return result;
2013 }
2014
2015 /*******************************************************************
2016  * static function to lookup the version id corresponding to an
2017  * long architecture string
2018  ******************************************************************/
2019
2020 static const struct print_architecture_table_node archi_table[]= {
2021
2022         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2023         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2024         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2025         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2026         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2027         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2028         {"Windows x64",          SPL_ARCH_X64,          3 },
2029         {NULL,                   "",            -1 }
2030 };
2031
2032 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2033                                    SPOOLSS_DRIVER_VERSION_NT35,
2034                                    SPOOLSS_DRIVER_VERSION_NT4,
2035                                    SPOOLSS_DRIVER_VERSION_200X,
2036                                    -1};
2037
2038 static int get_version_id(const char *arch)
2039 {
2040         int i;
2041
2042         for (i=0; archi_table[i].long_archi != NULL; i++)
2043         {
2044                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2045                         return (archi_table[i].version);
2046         }
2047
2048         return -1;
2049 }
2050
2051 /****************************************************************
2052  _spoolss_DeletePrinterDriver
2053 ****************************************************************/
2054
2055 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2056                                     struct spoolss_DeletePrinterDriver *r)
2057 {
2058
2059         struct spoolss_DriverInfo8 *info = NULL;
2060         int                             version;
2061         WERROR                          status;
2062         struct dcerpc_binding_handle *b;
2063         TALLOC_CTX *tmp_ctx = NULL;
2064         int i;
2065         bool found;
2066
2067         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2068            and not a printer admin, then fail */
2069
2070         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2071             !security_token_has_privilege(p->session_info->security_token,
2072                                           SEC_PRIV_PRINT_OPERATOR)) {
2073                 return WERR_ACCESS_DENIED;
2074         }
2075
2076         /* check that we have a valid driver name first */
2077
2078         if ((version = get_version_id(r->in.architecture)) == -1) {
2079                 return WERR_INVALID_ENVIRONMENT;
2080         }
2081
2082         tmp_ctx = talloc_new(p->mem_ctx);
2083         if (!tmp_ctx) {
2084                 return WERR_NOMEM;
2085         }
2086
2087         status = winreg_printer_binding_handle(tmp_ctx,
2088                                                get_session_info_system(),
2089                                                p->msg_ctx,
2090                                                &b);
2091         if (!W_ERROR_IS_OK(status)) {
2092                 goto done;
2093         }
2094
2095         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2096                 status = winreg_get_driver(tmp_ctx, b,
2097                                            r->in.architecture, r->in.driver,
2098                                            drv_cversion[i], &info);
2099                 if (!W_ERROR_IS_OK(status)) {
2100                         DEBUG(5, ("skipping del of driver with version %d\n",
2101                                   drv_cversion[i]));
2102                         continue;
2103                 }
2104                 found = true;
2105
2106                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2107                         status = WERR_PRINTER_DRIVER_IN_USE;
2108                         goto done;
2109                 }
2110
2111                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2112                 if (!W_ERROR_IS_OK(status)) {
2113                         DEBUG(0, ("failed del of driver with version %d\n",
2114                                   drv_cversion[i]));
2115                         goto done;
2116                 }
2117         }
2118         if (found == false) {
2119                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2120                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2121         } else {
2122                 status = WERR_OK;
2123         }
2124
2125 done:
2126         talloc_free(tmp_ctx);
2127
2128         return status;
2129 }
2130
2131 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2132                                   struct pipes_struct *p,
2133                                   struct spoolss_DeletePrinterDriverEx *r,
2134                                   struct dcerpc_binding_handle *b,
2135                                   struct spoolss_DriverInfo8 *info)
2136 {
2137         WERROR status;
2138         bool delete_files;
2139
2140         if (printer_driver_in_use(mem_ctx, b, info)) {
2141                 status = WERR_PRINTER_DRIVER_IN_USE;
2142                 goto done;
2143         }
2144
2145         /*
2146          * we have a couple of cases to consider.
2147          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2148          *     then the delete should fail if **any** files overlap with
2149          *     other drivers
2150          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2151          *     non-overlapping files
2152          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2153          *     are set, then do not delete any files
2154          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2155          */
2156
2157         delete_files = r->in.delete_flags
2158                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2159
2160
2161         if (delete_files) {
2162                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2163                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2164                         status = WERR_PRINTER_DRIVER_IN_USE;
2165                         goto done;
2166                 }
2167                 /*
2168                  * printer_driver_files_in_use() has trimmed overlapping files
2169                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2170                  */
2171         }
2172
2173
2174         status = winreg_del_driver(mem_ctx, b, info, info->version);
2175         if (!W_ERROR_IS_OK(status)) {
2176                 goto done;
2177         }
2178
2179         /*
2180          * now delete any associated files if delete_files is
2181          * true. Even if this part failes, we return succes
2182          * because the driver doesn not exist any more
2183          */
2184         if (delete_files) {
2185                 delete_driver_files(p->session_info, info);
2186         }
2187
2188 done:
2189         return status;
2190 }
2191
2192 /****************************************************************
2193  _spoolss_DeletePrinterDriverEx
2194 ****************************************************************/
2195
2196 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2197                                       struct spoolss_DeletePrinterDriverEx *r)
2198 {
2199         struct spoolss_DriverInfo8 *info = NULL;
2200         WERROR                          status;
2201         struct dcerpc_binding_handle *b;
2202         TALLOC_CTX *tmp_ctx = NULL;
2203         int i;
2204         bool found;
2205
2206         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2207            and not a printer admin, then fail */
2208
2209         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2210             !security_token_has_privilege(p->session_info->security_token,
2211                                           SEC_PRIV_PRINT_OPERATOR)) {
2212                 return WERR_ACCESS_DENIED;
2213         }
2214
2215         /* check that we have a valid driver name first */
2216         if (get_version_id(r->in.architecture) == -1) {
2217                 /* this is what NT returns */
2218                 return WERR_INVALID_ENVIRONMENT;
2219         }
2220
2221         tmp_ctx = talloc_new(p->mem_ctx);
2222         if (!tmp_ctx) {
2223                 return WERR_NOMEM;
2224         }
2225
2226         status = winreg_printer_binding_handle(tmp_ctx,
2227                                                get_session_info_system(),
2228                                                p->msg_ctx,
2229                                                &b);
2230         if (!W_ERROR_IS_OK(status)) {
2231                 goto done;
2232         }
2233
2234         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2235                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2236                  && (drv_cversion[i] != r->in.version)) {
2237                         continue;
2238                 }
2239
2240                 /* check if a driver with this version exists before delete */
2241                 status = winreg_get_driver(tmp_ctx, b,
2242                                            r->in.architecture, r->in.driver,
2243                                            drv_cversion[i], &info);
2244                 if (!W_ERROR_IS_OK(status)) {
2245                         DEBUG(5, ("skipping del of driver with version %d\n",
2246                                   drv_cversion[i]));
2247                         continue;
2248                 }
2249                 found = true;
2250
2251                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2252                 if (!W_ERROR_IS_OK(status)) {
2253                         DEBUG(0, ("failed to delete driver with version %d\n",
2254                                   drv_cversion[i]));
2255                         goto done;
2256                 }
2257         }
2258         if (found == false) {
2259                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2260                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2261         } else {
2262                 status = WERR_OK;
2263         }
2264
2265 done:
2266         talloc_free(tmp_ctx);
2267         return status;
2268 }
2269
2270
2271 /********************************************************************
2272  GetPrinterData on a printer server Handle.
2273 ********************************************************************/
2274
2275 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2276                                             const char *value,
2277                                             enum winreg_Type *type,
2278                                             union spoolss_PrinterData *data)
2279 {
2280         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2281
2282         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2283                 *type = REG_DWORD;
2284                 SIVAL(&data->value, 0, 0x00);
2285                 return WERR_OK;
2286         }
2287
2288         if (!strcasecmp_m(value, "BeepEnabled")) {
2289                 *type = REG_DWORD;
2290                 SIVAL(&data->value, 0, 0x00);
2291                 return WERR_OK;
2292         }
2293
2294         if (!strcasecmp_m(value, "EventLog")) {
2295                 *type = REG_DWORD;
2296                 /* formally was 0x1b */
2297                 SIVAL(&data->value, 0, 0x00);
2298                 return WERR_OK;
2299         }
2300
2301         if (!strcasecmp_m(value, "NetPopup")) {
2302                 *type = REG_DWORD;
2303                 SIVAL(&data->value, 0, 0x00);
2304                 return WERR_OK;
2305         }
2306
2307         if (!strcasecmp_m(value, "MajorVersion")) {
2308                 *type = REG_DWORD;
2309
2310                 /* Windows NT 4.0 seems to not allow uploading of drivers
2311                    to a server that reports 0x3 as the MajorVersion.
2312                    need to investigate more how Win2k gets around this .
2313                    -- jerry */
2314
2315                 if (RA_WINNT == get_remote_arch()) {
2316                         SIVAL(&data->value, 0, 0x02);
2317                 } else {
2318                         SIVAL(&data->value, 0, 0x03);
2319                 }
2320
2321                 return WERR_OK;
2322         }
2323
2324         if (!strcasecmp_m(value, "MinorVersion")) {
2325                 *type = REG_DWORD;
2326                 SIVAL(&data->value, 0, 0x00);
2327                 return WERR_OK;
2328         }
2329
2330         /* REG_BINARY
2331          *  uint32_t size        = 0x114
2332          *  uint32_t major       = 5
2333          *  uint32_t minor       = [0|1]
2334          *  uint32_t build       = [2195|2600]
2335          *  extra unicode string = e.g. "Service Pack 3"
2336          */
2337         if (!strcasecmp_m(value, "OSVersion")) {
2338                 DATA_BLOB blob;
2339                 enum ndr_err_code ndr_err;
2340                 struct spoolss_OSVersion os;
2341
2342                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
2343                                                       "spoolss", "os_major", 5);
2344                                                       /* Windows 2000 == 5.0 */
2345                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
2346                                                       "spoolss", "os_minor", 0);
2347                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
2348                                                       "spoolss", "os_build", 2195);
2349                 os.extra_string         = "";   /* leave extra string empty */
2350
2351                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2352                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2353                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2354                         return WERR_GENERAL_FAILURE;
2355                 }
2356
2357                 if (DEBUGLEVEL >= 10) {
2358                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2359                 }
2360
2361                 *type = REG_BINARY;
2362                 data->binary = blob;
2363
2364                 return WERR_OK;
2365         }
2366
2367
2368         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2369                 *type = REG_SZ;
2370
2371                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2372                 W_ERROR_HAVE_NO_MEMORY(data->string);
2373
2374                 return WERR_OK;
2375         }
2376
2377         if (!strcasecmp_m(value, "Architecture")) {
2378                 *type = REG_SZ;
2379                 data->string = talloc_strdup(mem_ctx,
2380                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2381                 W_ERROR_HAVE_NO_MEMORY(data->string);
2382
2383                 return WERR_OK;
2384         }
2385
2386         if (!strcasecmp_m(value, "DsPresent")) {
2387                 *type = REG_DWORD;
2388
2389                 /* only show the publish check box if we are a
2390                    member of a AD domain */
2391
2392                 if (lp_security() == SEC_ADS) {
2393                         SIVAL(&data->value, 0, 0x01);
2394                 } else {
2395                         SIVAL(&data->value, 0, 0x00);
2396                 }
2397                 return WERR_OK;
2398         }
2399
2400         if (!strcasecmp_m(value, "DNSMachineName")) {
2401                 const char *hostname = get_mydnsfullname();
2402
2403                 if (!hostname) {
2404                         return WERR_BADFILE;
2405                 }
2406
2407                 *type = REG_SZ;
2408                 data->string = talloc_strdup(mem_ctx, hostname);
2409                 W_ERROR_HAVE_NO_MEMORY(data->string);
2410
2411                 return WERR_OK;
2412         }
2413
2414         *type = REG_NONE;
2415
2416         return WERR_INVALID_PARAM;
2417 }
2418
2419 /****************************************************************
2420  _spoolss_GetPrinterData
2421 ****************************************************************/
2422
2423 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2424                                struct spoolss_GetPrinterData *r)
2425 {
2426         struct spoolss_GetPrinterDataEx r2;
2427
2428         r2.in.handle            = r->in.handle;
2429         r2.in.key_name          = "PrinterDriverData";
2430         r2.in.value_name        = r->in.value_name;
2431         r2.in.offered           = r->in.offered;
2432         r2.out.type             = r->out.type;
2433         r2.out.data             = r->out.data;
2434         r2.out.needed           = r->out.needed;
2435
2436         return _spoolss_GetPrinterDataEx(p, &r2);
2437 }
2438
2439 /*********************************************************
2440  Connect to the client machine.
2441 **********************************************************/
2442
2443 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2444                                       struct sockaddr_storage *client_ss, const char *remote_machine)
2445 {
2446         NTSTATUS ret;
2447         struct sockaddr_storage rm_addr;
2448         char addr[INET6_ADDRSTRLEN];
2449
2450         if ( is_zero_addr(client_ss) ) {
2451                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2452                         remote_machine));
2453                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2454                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2455                         return false;
2456                 }
2457                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2458         } else {
2459                 rm_addr = *client_ss;
2460                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2461                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2462                         addr));
2463         }
2464
2465         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2466                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2467                         addr));
2468                 return false;
2469         }
2470
2471         /* setup the connection */
2472         ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2473                 &rm_addr, 0, "IPC$", "IPC",
2474                 "", /* username */
2475                 "", /* domain */
2476                 "", /* password */
2477                 0, lp_client_signing());
2478
2479         if ( !NT_STATUS_IS_OK( ret ) ) {
2480                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2481                         remote_machine ));
2482                 return false;
2483         }
2484
2485         if ( smbXcli_conn_protocol((*pp_cli)->conn) != PROTOCOL_NT1 ) {
2486                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2487                 cli_shutdown(*pp_cli);
2488                 return false;
2489         }
2490
2491         /*
2492          * Ok - we have an anonymous connection to the IPC$ share.
2493          * Now start the NT Domain stuff :-).
2494          */
2495
2496         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2497         if (!NT_STATUS_IS_OK(ret)) {
2498                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2499                         remote_machine, nt_errstr(ret)));
2500                 cli_shutdown(*pp_cli);
2501                 return false;
2502         }
2503
2504         return true;
2505 }
2506
2507 /***************************************************************************
2508  Connect to the client.
2509 ****************************************************************************/
2510
2511 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2512                                         uint32_t localprinter,
2513                                         enum winreg_Type type,
2514                                         struct policy_handle *handle,
2515                                         struct notify_back_channel **_chan,
2516                                         struct sockaddr_storage *client_ss,
2517                                         struct messaging_context *msg_ctx)
2518 {
2519         WERROR result;
2520         NTSTATUS status;
2521         struct notify_back_channel *chan;
2522
2523         for (chan = back_channels; chan; chan = chan->next) {
2524                 if (memcmp(&chan->client_address, client_ss,
2525                            sizeof(struct sockaddr_storage)) == 0) {
2526                         break;
2527                 }
2528         }
2529
2530         /*
2531          * If it's the first connection, contact the client
2532          * and connect to the IPC$ share anonymously
2533          */
2534         if (!chan) {
2535                 fstring unix_printer;
2536
2537                 /* the +2 is to strip the leading 2 backslashs */
2538                 fstrcpy(unix_printer, printer + 2);
2539
2540                 chan = talloc_zero(NULL, struct notify_back_channel);
2541                 if (!chan) {
2542                         return false;
2543                 }
2544                 chan->client_address = *client_ss;
2545
2546                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2547                         TALLOC_FREE(chan);
2548                         return false;
2549                 }
2550
2551                 DLIST_ADD(back_channels, chan);
2552
2553                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2554                                    receive_notify2_message_list);
2555         }
2556
2557         if (chan->cli_pipe == NULL ||
2558             chan->cli_pipe->binding_handle == NULL) {
2559                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2560                         "NULL %s for printer %s\n",
2561                         chan->cli_pipe == NULL ?
2562                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2563                         printer));
2564                 return false;
2565         }
2566
2567         /*
2568          * Tell the specific printing tdb we want messages for this printer
2569          * by registering our PID.
2570          */
2571
2572         if (!print_notify_register_pid(snum)) {
2573                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2574                           printer));
2575         }
2576
2577         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2578                                                  talloc_tos(),
2579                                                  printer,
2580                                                  localprinter,
2581                                                  type,
2582                                                  0,
2583                                                  NULL,
2584                                                  handle,
2585                                                  &result);
2586         if (!NT_STATUS_IS_OK(status)) {
2587                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2588                 result = ntstatus_to_werror(status);
2589         } else if (!W_ERROR_IS_OK(result)) {
2590                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2591         }
2592
2593         chan->active_connections++;
2594         *_chan = chan;
2595
2596         return (W_ERROR_IS_OK(result));
2597 }
2598
2599 /****************************************************************
2600  ****************************************************************/
2601
2602 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2603                                                              const struct spoolss_NotifyOption *r)
2604 {
2605         struct spoolss_NotifyOption *option;
2606         uint32_t i,k;
2607
2608         if (!r) {
2609                 return NULL;
2610         }
2611
2612         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2613         if (!option) {
2614                 return NULL;
2615         }
2616
2617         *option = *r;
2618
2619         if (!option->count) {
2620                 return option;
2621         }
2622
2623         option->types = talloc_zero_array(option,
2624                 struct spoolss_NotifyOptionType, option->count);
2625         if (!option->types) {
2626                 talloc_free(option);
2627                 return NULL;
2628         }
2629
2630         for (i=0; i < option->count; i++) {
2631                 option->types[i] = r->types[i];
2632
2633                 if (option->types[i].count) {
2634                         option->types[i].fields = talloc_zero_array(option,
2635                                 union spoolss_Field, option->types[i].count);
2636                         if (!option->types[i].fields) {
2637                                 talloc_free(option);
2638                                 return NULL;
2639                         }
2640                         for (k=0; k<option->types[i].count; k++) {
2641                                 option->types[i].fields[k] =
2642                                         r->types[i].fields[k];
2643                         }
2644                 }
2645         }
2646
2647         return option;
2648 }
2649
2650 /****************************************************************
2651  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2652  *
2653  * before replying OK: status=0 a rpc call is made to the workstation
2654  * asking ReplyOpenPrinter
2655  *
2656  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2657  * called from api_spoolss_rffpcnex
2658 ****************************************************************/
2659
2660 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2661                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2662 {
2663         int snum = -1;
2664         struct spoolss_NotifyOption *option = r->in.notify_options;
2665         struct sockaddr_storage client_ss;
2666         ssize_t client_len;
2667
2668         /* store the notify value in the printer struct */
2669
2670         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2671
2672         if (!Printer) {
2673                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2674                         "Invalid handle (%s:%u:%u).\n",
2675                         OUR_HANDLE(r->in.handle)));
2676                 return WERR_BADFID;
2677         }
2678
2679         Printer->notify.flags           = r->in.flags;
2680         Printer->notify.options         = r->in.options;
2681         Printer->notify.printerlocal    = r->in.printer_local;
2682         Printer->notify.msg_ctx         = p->msg_ctx;
2683
2684         TALLOC_FREE(Printer->notify.option);
2685         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2686
2687         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2688
2689         /* Connect to the client machine and send a ReplyOpenPrinter */
2690
2691         if ( Printer->printer_type == SPLHND_SERVER)
2692                 snum = -1;
2693         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2694                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2695                 return WERR_BADFID;
2696
2697         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2698                   "remote_address is %s\n",
2699                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2700
2701         if (!lp_print_notify_backchannel(snum)) {
2702                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2703                         "backchannel disabled\n"));
2704                 return WERR_SERVER_UNAVAILABLE;
2705         }
2706
2707         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2708                                                   (struct sockaddr *) &client_ss,
2709                                                   sizeof(struct sockaddr_storage));
2710         if (client_len < 0) {
2711                 return WERR_NOMEM;
2712         }
2713
2714         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2715                                         Printer->notify.printerlocal, REG_SZ,
2716                                         &Printer->notify.cli_hnd,
2717                                         &Printer->notify.cli_chan,
2718                                         &client_ss, p->msg_ctx)) {
2719                 return WERR_SERVER_UNAVAILABLE;
2720         }
2721
2722         return WERR_OK;
2723 }
2724
2725 /*******************************************************************
2726  * fill a notify_info_data with the servername
2727  ********************************************************************/
2728
2729 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2730                                        int snum,
2731                                        struct spoolss_Notify *data,
2732                                        print_queue_struct *queue,
2733                                        struct spoolss_PrinterInfo2 *pinfo2,
2734                                        TALLOC_CTX *mem_ctx)
2735 {
2736         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2737 }
2738
2739 /*******************************************************************
2740  * fill a notify_info_data with the printername (not including the servername).
2741  ********************************************************************/
2742
2743 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2744                                         int snum,
2745                                         struct spoolss_Notify *data,
2746                                         print_queue_struct *queue,
2747                                         struct spoolss_PrinterInfo2 *pinfo2,
2748                                         TALLOC_CTX *mem_ctx)
2749 {
2750         /* the notify name should not contain the \\server\ part */
2751         const char *p = strrchr(pinfo2->printername, '\\');
2752
2753         if (!p) {
2754                 p = pinfo2->printername;
2755         } else {
2756                 p++;
2757         }
2758
2759         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2760 }
2761
2762 /*******************************************************************
2763  * fill a notify_info_data with the servicename
2764  ********************************************************************/
2765
2766 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2767                                       int snum,
2768                                       struct spoolss_Notify *data,
2769                                       print_queue_struct *queue,
2770                                       struct spoolss_PrinterInfo2 *pinfo2,
2771                                       TALLOC_CTX *mem_ctx)
2772 {
2773         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2774 }
2775
2776 /*******************************************************************
2777  * fill a notify_info_data with the port name
2778  ********************************************************************/
2779
2780 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2781                                      int snum,
2782                                      struct spoolss_Notify *data,
2783                                      print_queue_struct *queue,
2784                                      struct spoolss_PrinterInfo2 *pinfo2,
2785                                      TALLOC_CTX *mem_ctx)
2786 {
2787         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2788 }
2789
2790 /*******************************************************************
2791  * fill a notify_info_data with the printername
2792  * but it doesn't exist, have to see what to do
2793  ********************************************************************/
2794
2795 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2796                                        int snum,
2797                                        struct spoolss_Notify *data,
2798                                        print_queue_struct *queue,
2799                                        struct spoolss_PrinterInfo2 *pinfo2,
2800                                        TALLOC_CTX *mem_ctx)
2801 {
2802         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2803 }
2804
2805 /*******************************************************************
2806  * fill a notify_info_data with the comment
2807  ********************************************************************/
2808
2809 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2810                                    int snum,
2811                                    struct spoolss_Notify *data,
2812                                    print_queue_struct *queue,
2813                                    struct spoolss_PrinterInfo2 *pinfo2,
2814                                    TALLOC_CTX *mem_ctx)
2815 {
2816         const char *p;
2817
2818         if (*pinfo2->comment == '\0') {
2819                 p = lp_comment(talloc_tos(), snum);
2820         } else {
2821                 p = pinfo2->comment;
2822         }
2823
2824         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2825 }
2826
2827 /*******************************************************************
2828  * fill a notify_info_data with the comment
2829  * location = "Room 1, floor 2, building 3"
2830  ********************************************************************/
2831
2832 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2833                                     int snum,
2834                                     struct spoolss_Notify *data,
2835                                     print_queue_struct *queue,
2836                                     struct spoolss_PrinterInfo2 *pinfo2,
2837                                     TALLOC_CTX *mem_ctx)
2838 {
2839         const char *loc = pinfo2->location;
2840         NTSTATUS status;
2841
2842         status = printer_list_get_printer(mem_ctx,
2843                                           pinfo2->sharename,
2844                                           NULL,
2845                                           &loc,
2846                                           NULL);
2847         if (NT_STATUS_IS_OK(status)) {
2848                 if (loc == NULL) {
2849                         loc = pinfo2->location;
2850                 }
2851         }
2852
2853         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2854 }
2855
2856 /*******************************************************************
2857  * fill a notify_info_data with the device mode
2858  * jfm:xxxx don't to it for know but that's a real problem !!!
2859  ********************************************************************/
2860
2861 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2862                                    int snum,
2863                                    struct spoolss_Notify *data,
2864                                    print_queue_struct *queue,
2865                                    struct spoolss_PrinterInfo2 *pinfo2,
2866                                    TALLOC_CTX *mem_ctx)
2867 {
2868         /* for a dummy implementation we have to zero the fields */
2869         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2870 }
2871
2872 /*******************************************************************
2873  * fill a notify_info_data with the separator file name
2874  ********************************************************************/
2875
2876 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2877                                    int snum,
2878                                    struct spoolss_Notify *data,
2879                                    print_queue_struct *queue,
2880                                    struct spoolss_PrinterInfo2 *pinfo2,
2881                                    TALLOC_CTX *mem_ctx)
2882 {
2883         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2884 }
2885
2886 /*******************************************************************
2887  * fill a notify_info_data with the print processor
2888  * jfm:xxxx return always winprint to indicate we don't do anything to it
2889  ********************************************************************/
2890
2891 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2892                                            int snum,
2893                                            struct spoolss_Notify *data,
2894                                            print_queue_struct *queue,
2895                                            struct spoolss_PrinterInfo2 *pinfo2,
2896                                            TALLOC_CTX *mem_ctx)
2897 {
2898         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2899 }
2900
2901 /*******************************************************************
2902  * fill a notify_info_data with the print processor options
2903  * jfm:xxxx send an empty string
2904  ********************************************************************/
2905
2906 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2907                                       int snum,
2908                                       struct spoolss_Notify *data,
2909                                       print_queue_struct *queue,
2910                                       struct spoolss_PrinterInfo2 *pinfo2,
2911                                       TALLOC_CTX *mem_ctx)
2912 {
2913         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2914 }
2915
2916 /*******************************************************************
2917  * fill a notify_info_data with the data type
2918  * jfm:xxxx always send RAW as data type
2919  ********************************************************************/
2920
2921 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2922                                     int snum,
2923                                     struct spoolss_Notify *data,
2924                                     print_queue_struct *queue,
2925                                     struct spoolss_PrinterInfo2 *pinfo2,
2926                                     TALLOC_CTX *mem_ctx)
2927 {
2928         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2929 }
2930
2931 /*******************************************************************
2932  * fill a notify_info_data with the security descriptor
2933  * jfm:xxxx send an null pointer to say no security desc
2934  * have to implement security before !
2935  ********************************************************************/
2936
2937 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2938                                          int snum,
2939                                          struct spoolss_Notify *data,
2940                                          print_queue_struct *queue,
2941                                          struct spoolss_PrinterInfo2 *pinfo2,
2942                                          TALLOC_CTX *mem_ctx)
2943 {
2944         if (pinfo2->secdesc == NULL) {
2945                 data->data.sd.sd = NULL;
2946         } else {
2947                 data->data.sd.sd = security_descriptor_copy(mem_ctx,
2948                                                             pinfo2->secdesc);
2949         }
2950         data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2951                                                              0);
2952 }
2953
2954 /*******************************************************************
2955  * fill a notify_info_data with the attributes
2956  * jfm:xxxx a samba printer is always shared
2957  ********************************************************************/
2958
2959 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2960                                       int snum,
2961                                       struct spoolss_Notify *data,
2962                                       print_queue_struct *queue,
2963                                       struct spoolss_PrinterInfo2 *pinfo2,
2964                                       TALLOC_CTX *mem_ctx)
2965 {
2966         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2967 }
2968
2969 /*******************************************************************
2970  * fill a notify_info_data with the priority
2971  ********************************************************************/
2972
2973 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2974                                     int snum,
2975                                     struct spoolss_Notify *data,
2976                                     print_queue_struct *queue,
2977                                     struct spoolss_PrinterInfo2 *pinfo2,
2978                                     TALLOC_CTX *mem_ctx)
2979 {
2980         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2981 }
2982
2983 /*******************************************************************
2984  * fill a notify_info_data with the default priority
2985  ********************************************************************/
2986
2987 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2988                                             int snum,
2989                                             struct spoolss_Notify *data,
2990                                             print_queue_struct *queue,
2991                                             struct spoolss_PrinterInfo2 *pinfo2,
2992                                             TALLOC_CTX *mem_ctx)
2993 {
2994         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2995 }
2996
2997 /*******************************************************************
2998  * fill a notify_info_data with the start time
2999  ********************************************************************/
3000
3001 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3002                                       int snum,
3003                                       struct spoolss_Notify *data,
3004                                       print_queue_struct *queue,
3005                                       struct spoolss_PrinterInfo2 *pinfo2,
3006                                       TALLOC_CTX *mem_ctx)
3007 {
3008         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3009 }
3010
3011 /*******************************************************************
3012  * fill a notify_info_data with the until time
3013  ********************************************************************/
3014
3015 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3016                                       int snum,
3017                                       struct spoolss_Notify *data,
3018                                       print_queue_struct *queue,
3019                                       struct spoolss_PrinterInfo2 *pinfo2,
3020                                       TALLOC_CTX *mem_ctx)
3021 {
3022         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3023 }
3024
3025 /*******************************************************************
3026  * fill a notify_info_data with the status
3027  ********************************************************************/
3028
3029 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3030                                   int snum,
3031                                   struct spoolss_Notify *data,
3032                                   print_queue_struct *queue,
3033                                   struct spoolss_PrinterInfo2 *pinfo2,
3034                                   TALLOC_CTX *mem_ctx)
3035 {
3036         print_status_struct status;
3037
3038         print_queue_length(msg_ctx, snum, &status);
3039         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3040 }
3041
3042 /*******************************************************************
3043  * fill a notify_info_data with the number of jobs queued
3044  ********************************************************************/
3045
3046 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3047                                  int snum,
3048                                  struct spoolss_Notify *data,
3049                                  print_queue_struct *queue,
3050                                  struct spoolss_PrinterInfo2 *pinfo2,
3051                                  TALLOC_CTX *mem_ctx)
3052 {
3053         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3054                 data, print_queue_length(msg_ctx, snum, NULL));
3055 }
3056
3057 /*******************************************************************
3058  * fill a notify_info_data with the average ppm
3059  ********************************************************************/
3060
3061 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3062                                        int snum,
3063                                        struct spoolss_Notify *data,
3064                                        print_queue_struct *queue,
3065                                        struct spoolss_PrinterInfo2 *pinfo2,
3066                                        TALLOC_CTX *mem_ctx)
3067 {
3068         /* always respond 8 pages per minutes */
3069         /* a little hard ! */
3070         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3071 }
3072
3073 /*******************************************************************
3074  * fill a notify_info_data with username
3075  ********************************************************************/
3076
3077 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3078                                     int snum,
3079                                     struct spoolss_Notify *data,
3080                                     print_queue_struct *queue,
3081                                     struct spoolss_PrinterInfo2 *pinfo2,
3082                                     TALLOC_CTX *mem_ctx)
3083 {
3084         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3085 }
3086
3087 /*******************************************************************
3088  * fill a notify_info_data with job status
3089  ********************************************************************/
3090
3091 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3092                                       int snum,
3093                                       struct spoolss_Notify *data,
3094                                       print_queue_struct *queue,
3095                                       struct spoolss_PrinterInfo2 *pinfo2,
3096                                       TALLOC_CTX *mem_ctx)
3097 {
3098         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3099 }
3100
3101 /*******************************************************************
3102  * fill a notify_info_data with job name
3103  ********************************************************************/
3104
3105 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3106                                     int snum,
3107                                     struct spoolss_Notify *data,
3108                                     print_queue_struct *queue,
3109                                     struct spoolss_PrinterInfo2 *pinfo2,
3110                                     TALLOC_CTX *mem_ctx)
3111 {
3112         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3113 }
3114
3115 /*******************************************************************
3116  * fill a notify_info_data with job status
3117  ********************************************************************/
3118
3119 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3120                                              int snum,
3121                                              struct spoolss_Notify *data,
3122                                              print_queue_struct *queue,
3123                                              struct spoolss_PrinterInfo2 *pinfo2,
3124                                              TALLOC_CTX *mem_ctx)
3125 {
3126         /*
3127          * Now we're returning job status codes we just return a "" here. JRA.
3128          */
3129
3130         const char *p = "";
3131
3132 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3133         p = "unknown";
3134
3135         switch (queue->status) {
3136         case LPQ_QUEUED:
3137                 p = "Queued";
3138                 break;
3139         case LPQ_PAUSED:
3140                 p = "";    /* NT provides the paused string */
3141                 break;
3142         case LPQ_SPOOLING:
3143                 p = "Spooling";
3144                 break;
3145         case LPQ_PRINTING:
3146                 p = "Printing";
3147                 break;
3148         }
3149 #endif /* NO LONGER NEEDED. */
3150
3151         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3152 }
3153
3154 /*******************************************************************
3155  * fill a notify_info_data with job time
3156  ********************************************************************/
3157
3158 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3159                                     int snum,
3160                                     struct spoolss_Notify *data,
3161                                     print_queue_struct *queue,
3162                                     struct spoolss_PrinterInfo2 *pinfo2,
3163                                     TALLOC_CTX *mem_ctx)
3164 {
3165         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3166 }
3167
3168 /*******************************************************************
3169  * fill a notify_info_data with job size
3170  ********************************************************************/
3171
3172 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3173                                     int snum,
3174                                     struct spoolss_Notify *data,
3175                                     print_queue_struct *queue,
3176                                     struct spoolss_PrinterInfo2 *pinfo2,
3177                                     TALLOC_CTX *mem_ctx)
3178 {
3179         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3180 }
3181
3182 /*******************************************************************
3183  * fill a notify_info_data with page info
3184  ********************************************************************/
3185 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3186                                        int snum,
3187                                 struct spoolss_Notify *data,
3188                                 print_queue_struct *queue,
3189                                 struct spoolss_PrinterInfo2 *pinfo2,
3190                                 TALLOC_CTX *mem_ctx)
3191 {
3192         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3193 }
3194
3195 /*******************************************************************
3196  * fill a notify_info_data with pages printed info.
3197  ********************************************************************/
3198 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3199                                          int snum,
3200                                 struct spoolss_Notify *data,
3201                                 print_queue_struct *queue,
3202                                 struct spoolss_PrinterInfo2 *pinfo2,
3203                                 TALLOC_CTX *mem_ctx)
3204 {
3205         /* Add code when back-end tracks this */
3206         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3207 }
3208
3209 /*******************************************************************
3210  Fill a notify_info_data with job position.
3211  ********************************************************************/
3212
3213 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3214                                         int snum,
3215                                         struct spoolss_Notify *data,
3216                                         print_queue_struct *queue,
3217                                         struct spoolss_PrinterInfo2 *pinfo2,
3218                                         TALLOC_CTX *mem_ctx)
3219 {
3220         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3221 }
3222
3223 /*******************************************************************
3224  Fill a notify_info_data with submitted time.
3225  ********************************************************************/
3226
3227 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3228                                           int snum,
3229                                           struct spoolss_Notify *data,
3230                                           print_queue_struct *queue,
3231                                           struct spoolss_PrinterInfo2 *pinfo2,
3232                                           TALLOC_CTX *mem_ctx)
3233 {
3234         data->data.string.string = NULL;
3235         data->data.string.size = 0;
3236
3237         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3238                                &data->data.string.string,
3239                                &data->data.string.size);
3240
3241 }
3242
3243 struct s_notify_info_data_table
3244 {
3245         enum spoolss_NotifyType type;
3246         uint16_t field;
3247         const char *name;
3248         enum spoolss_NotifyTable variable_type;
3249         void (*fn) (struct messaging_context *msg_ctx,
3250                     int snum, struct spoolss_Notify *data,
3251                     print_queue_struct *queue,
3252                     struct spoolss_PrinterInfo2 *pinfo2,
3253                     TALLOC_CTX *mem_ctx);
3254 };
3255
3256 /* A table describing the various print notification constants and
3257    whether the notification data is a pointer to a variable sized
3258    buffer, a one value uint32_t or a two value uint32_t. */
3259
3260 static const struct s_notify_info_data_table notify_info_data_table[] =
3261 {
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3288 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3289 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3290 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3291 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3305 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3306 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3311 };
3312
3313 /*******************************************************************
3314  Return the variable_type of info_data structure.
3315 ********************************************************************/
3316
3317 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3318                                                                   uint16_t field)
3319 {
3320         int i=0;
3321
3322         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3323                 if ( (notify_info_data_table[i].type == type) &&
3324                      (notify_info_data_table[i].field == field) ) {
3325                         return notify_info_data_table[i].variable_type;
3326                 }
3327         }
3328
3329         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3330
3331         return (enum spoolss_NotifyTable) 0;
3332 }
3333
3334 /****************************************************************************
3335 ****************************************************************************/
3336
3337 static bool search_notify(enum spoolss_NotifyType type,
3338                           uint16_t field,
3339                           int *value)
3340 {
3341         int i;
3342
3343         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3344                 if (notify_info_data_table[i].type == type &&
3345                     notify_info_data_table[i].field == field &&
3346                     notify_info_data_table[i].fn != NULL) {
3347                         *value = i;
3348                         return true;
3349                 }
3350         }
3351
3352         return false;
3353 }
3354
3355 /****************************************************************************
3356 ****************************************************************************/
3357
3358 static void construct_info_data(struct spoolss_Notify *info_data,
3359                                 enum spoolss_NotifyType type,
3360                                 uint16_t field, int id)
3361 {
3362         info_data->type                 = type;
3363         info_data->field.field          = field;
3364         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3365         info_data->job_id               = id;
3366 }
3367
3368 /*******************************************************************
3369  *
3370  * fill a notify_info struct with info asked
3371  *
3372  ********************************************************************/
3373
3374 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3375                                           struct printer_handle *print_hnd,
3376                                           struct spoolss_NotifyInfo *info,
3377                                           struct spoolss_PrinterInfo2 *pinfo2,
3378                                           int snum,
3379                                           const struct spoolss_NotifyOptionType *option_type,
3380                                           uint32_t id,
3381                                           TALLOC_CTX *mem_ctx)
3382 {
3383         int field_num,j;
3384         enum spoolss_NotifyType type;
3385         uint16_t field;
3386
3387         struct spoolss_Notify *current_data;
3388
3389         type = option_type->type;
3390
3391         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3392                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3393                 option_type->count, lp_servicename(talloc_tos(), snum)));
3394
3395         for(field_num=0; field_num < option_type->count; field_num++) {
3396                 field = option_type->fields[field_num].field;
3397
3398                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3399
3400                 if (!search_notify(type, field, &j) )
3401                         continue;
3402
3403                 info->notifies = talloc_realloc(info, info->notifies,
3404                                                       struct spoolss_Notify,
3405                                                       info->count + 1);
3406                 if (info->notifies == NULL) {
3407                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3408                         return false;
3409                 }
3410
3411                 current_data = &info->notifies[info->count];
3412
3413                 construct_info_data(current_data, type, field, id);
3414
3415                 DEBUG(10, ("construct_notify_printer_info: "
3416                            "calling [%s]  snum=%d  printername=[%s])\n",
3417                            notify_info_data_table[j].name, snum,
3418                            pinfo2->printername));
3419
3420                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3421                                              NULL, pinfo2, mem_ctx);
3422
3423                 info->count++;
3424         }
3425
3426         return true;
3427 }
3428
3429 /*******************************************************************
3430  *
3431  * fill a notify_info struct with info asked
3432  *
3433  ********************************************************************/
3434
3435 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3436                                        print_queue_struct *queue,
3437                                        struct spoolss_NotifyInfo *info,
3438                                        struct spoolss_PrinterInfo2 *pinfo2,
3439                                        int snum,
3440                                        const struct spoolss_NotifyOptionType *option_type,
3441                                        uint32_t id,
3442                                        TALLOC_CTX *mem_ctx)
3443 {
3444         int field_num,j;
3445         enum spoolss_NotifyType type;
3446         uint16_t field;
3447         struct spoolss_Notify *current_data;
3448
3449         DEBUG(4,("construct_notify_jobs_info\n"));
3450
3451         type = option_type->type;
3452
3453         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3454                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3455                 option_type->count));
3456
3457         for(field_num=0; field_num<option_type->count; field_num++) {
3458                 field = option_type->fields[field_num].field;
3459
3460                 if (!search_notify(type, field, &j) )
3461                         continue;
3462
3463                 info->notifies = talloc_realloc(info, info->notifies,
3464                                                       struct spoolss_Notify,
3465                                                       info->count + 1);
3466                 if (info->notifies == NULL) {
3467                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3468                         return false;
3469                 }
3470
3471                 current_data=&(info->notifies[info->count]);
3472
3473                 construct_info_data(current_data, type, field, id);
3474                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3475                                              queue, pinfo2, mem_ctx);
3476                 info->count++;
3477         }
3478
3479         return true;
3480 }
3481
3482 /*
3483  * JFM: The enumeration is not that simple, it's even non obvious.
3484  *
3485  * let's take an example: I want to monitor the PRINTER SERVER for
3486  * the printer's name and the number of jobs currently queued.
3487  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3488  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3489  *
3490  * I have 3 printers on the back of my server.
3491  *
3492  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3493  * structures.
3494  *   Number     Data                    Id
3495  *      1       printer 1 name          1
3496  *      2       printer 1 cjob          1
3497  *      3       printer 2 name          2
3498  *      4       printer 2 cjob          2
3499  *      5       printer 3 name          3
3500  *      6       printer 3 name          3
3501  *
3502  * that's the print server case, the printer case is even worse.
3503  */
3504
3505 /*******************************************************************
3506  *
3507  * enumerate all printers on the printserver
3508  * fill a notify_info struct with info asked
3509  *
3510  ********************************************************************/
3511
3512 static WERROR printserver_notify_info(struct pipes_struct *p,
3513                                       struct policy_handle *hnd,
3514                                       struct spoolss_NotifyInfo *info,
3515                                       TALLOC_CTX *mem_ctx)
3516 {
3517         int snum;
3518         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3519         int n_services=lp_numservices();
3520         int i;
3521         struct spoolss_NotifyOption *option;
3522         struct spoolss_NotifyOptionType option_type;
3523         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3524         WERROR result;
3525
3526         DEBUG(4,("printserver_notify_info\n"));
3527
3528         if (!Printer)
3529                 return WERR_BADFID;
3530
3531         option = Printer->notify.option;
3532
3533         info->version   = 2;
3534         info->notifies  = NULL;
3535         info->count     = 0;
3536
3537         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3538            sending a ffpcn() request first */
3539
3540         if ( !option )
3541                 return WERR_BADFID;
3542
3543         for (i=0; i<option->count; i++) {
3544                 option_type = option->types[i];
3545
3546                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3547                         continue;
3548
3549                 for (snum = 0; snum < n_services; snum++) {
3550                         if (!lp_browseable(snum) ||
3551                             !lp_snum_ok(snum) ||
3552                             !lp_printable(snum)) {
3553                                 continue; /* skip */
3554                         }
3555
3556                         /* Maybe we should use the SYSTEM session_info here... */
3557                         result = winreg_get_printer_internal(mem_ctx,
3558                                                     get_session_info_system(),
3559                                                     p->msg_ctx,
3560                                                     lp_servicename(talloc_tos(), snum),
3561                                                     &pinfo2);
3562                         if (!W_ERROR_IS_OK(result)) {
3563                                 DEBUG(4, ("printserver_notify_info: "
3564                                           "Failed to get printer [%s]\n",
3565                                           lp_servicename(talloc_tos(), snum)));
3566                                 continue;
3567                         }
3568
3569
3570                         construct_notify_printer_info(p->msg_ctx,
3571                                                       Printer, info,
3572                                                       pinfo2, snum,
3573                                                       &option_type, snum,
3574                                                       mem_ctx);
3575
3576                         TALLOC_FREE(pinfo2);
3577                 }
3578         }
3579
3580 #if 0
3581         /*
3582          * Debugging information, don't delete.
3583          */
3584
3585         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3586         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3587         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3588
3589         for (i=0; i<info->count; i++) {
3590                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3591                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3592                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3593         }
3594 #endif
3595
3596         return WERR_OK;
3597 }
3598
3599 /*******************************************************************
3600  *
3601  * fill a notify_info struct with info asked
3602  *
3603  ********************************************************************/
3604
3605 static WERROR printer_notify_info(struct pipes_struct *p,
3606                                   struct policy_handle *hnd,
3607                                   struct spoolss_NotifyInfo *info,
3608                                   TALLOC_CTX *mem_ctx)
3609 {
3610         int snum;
3611         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3612         int i;
3613         uint32_t id;
3614         struct spoolss_NotifyOption *option;
3615         struct spoolss_NotifyOptionType option_type;
3616         int count,j;
3617         print_queue_struct *queue=NULL;
3618         print_status_struct status;
3619         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3620         WERROR result;
3621         struct tdb_print_db *pdb;
3622
3623         DEBUG(4,("printer_notify_info\n"));
3624
3625         if (!Printer)
3626                 return WERR_BADFID;
3627
3628         option = Printer->notify.option;
3629         id = 0x0;
3630
3631         info->version   = 2;
3632         info->notifies  = NULL;
3633         info->count     = 0;
3634
3635         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3636            sending a ffpcn() request first */
3637
3638         if ( !option )
3639                 return WERR_BADFID;
3640
3641         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3642                 return WERR_BADFID;
3643         }
3644
3645         pdb = get_print_db_byname(Printer->sharename);
3646         if (pdb == NULL) {
3647                 return WERR_BADFID;
3648         }
3649
3650         /* Maybe we should use the SYSTEM session_info here... */
3651         result = winreg_get_printer_internal(mem_ctx,
3652                                     get_session_info_system(),
3653                                     p->msg_ctx,
3654                                     lp_servicename(talloc_tos(), snum), &pinfo2);
3655         if (!W_ERROR_IS_OK(result)) {
3656                 result = WERR_BADFID;
3657                 goto err_pdb_drop;
3658         }
3659
3660         /*
3661          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3662          * correct servername.
3663          */
3664         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3665         if (pinfo2->servername == NULL) {
3666                 result = WERR_NOMEM;
3667                 goto err_pdb_drop;
3668         }
3669
3670         for (i = 0; i < option->count; i++) {
3671                 option_type = option->types[i];
3672
3673                 switch (option_type.type) {
3674                 case PRINTER_NOTIFY_TYPE:
3675                         if (construct_notify_printer_info(p->msg_ctx,
3676                                                           Printer, info,
3677                                                           pinfo2, snum,
3678                                                           &option_type, id,
3679                                                           mem_ctx)) {
3680                                 id--;
3681                         }
3682                         break;
3683
3684                 case JOB_NOTIFY_TYPE:
3685
3686                         count = print_queue_status(p->msg_ctx, snum, &queue,
3687                                                    &status);
3688
3689                         for (j = 0; j < count; j++) {
3690                                 uint32_t jobid;
3691                                 jobid = sysjob_to_jobid_pdb(pdb,
3692                                                             queue[j].sysjob);
3693                                 if (jobid == (uint32_t)-1) {
3694                                         DEBUG(2, ("ignoring untracked job %d\n",
3695                                                   queue[j].sysjob));
3696                                         continue;
3697                                 }
3698                                 /* FIXME check return value */
3699                                 construct_notify_jobs_info(p->msg_ctx,
3700                                                            &queue[j], info,
3701                                                            pinfo2, snum,
3702                                                            &option_type,
3703                                                            jobid,
3704                                                            mem_ctx);
3705                         }
3706
3707                         SAFE_FREE(queue);
3708                         break;
3709                 }
3710         }
3711
3712         /*
3713          * Debugging information, don't delete.
3714          */
3715         /*
3716         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3717         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3718         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3719
3720         for (i=0; i<info->count; i++) {
3721                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3722                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3723                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3724         }
3725         */
3726
3727         talloc_free(pinfo2);
3728         result = WERR_OK;
3729 err_pdb_drop:
3730         release_print_db(pdb);
3731         return result;
3732 }
3733
3734 /****************************************************************
3735  _spoolss_RouterRefreshPrinterChangeNotify
3736 ****************************************************************/
3737
3738 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3739                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3740 {
3741         struct spoolss_NotifyInfo *info;
3742
3743         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3744         WERROR result = WERR_BADFID;
3745
3746         /* we always have a spoolss_NotifyInfo struct */
3747         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3748         if (!info) {
3749                 result = WERR_NOMEM;
3750                 goto done;
3751         }
3752
3753         *r->out.info = info;
3754
3755         if (!Printer) {
3756                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3757                         "Invalid handle (%s:%u:%u).\n",
3758                         OUR_HANDLE(r->in.handle)));
3759                 goto done;
3760         }
3761
3762         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3763
3764         /*
3765          *      We are now using the change value, and
3766          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3767          *      I don't have a global notification system, I'm sending back all the
3768          *      information even when _NOTHING_ has changed.
3769          */
3770
3771         /* We need to keep track of the change value to send back in
3772            RRPCN replies otherwise our updates are ignored. */
3773
3774         Printer->notify.fnpcn = true;
3775
3776         if (Printer->notify.cli_chan != NULL &&
3777             Printer->notify.cli_chan->active_connections > 0) {
3778                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3779                         "Saving change value in request [%x]\n",
3780                         r->in.change_low));
3781                 Printer->notify.change = r->in.change_low;
3782         }
3783
3784         /* just ignore the spoolss_NotifyOption */
3785
3786         switch (Printer->printer_type) {
3787                 case SPLHND_SERVER:
3788                         result = printserver_notify_info(p, r->in.handle,
3789                                                          info, p->mem_ctx);
3790                         break;
3791
3792                 case SPLHND_PRINTER:
3793                         result = printer_notify_info(p, r->in.handle,
3794                                                      info, p->mem_ctx);
3795                         break;
3796         }
3797
3798         Printer->notify.fnpcn = false;
3799
3800 done:
3801         return result;
3802 }
3803
3804 /********************************************************************
3805  ********************************************************************/
3806
3807 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3808                                  const char *servername,
3809                                  const char *printername,
3810                                  const char **printername_p)
3811 {
3812         /* FIXME: add lp_force_printername() */
3813
3814         if (servername == NULL) {
3815                 *printername_p = talloc_strdup(mem_ctx, printername);
3816                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3817                 return WERR_OK;
3818         }
3819
3820         if (servername[0] == '\\' && servername[1] == '\\') {
3821                 servername += 2;
3822         }
3823
3824         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3825         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3826
3827         return WERR_OK;
3828 }
3829
3830 /********************************************************************
3831  ********************************************************************/
3832
3833 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3834                                           const char *printername)
3835 {
3836         if (dm == NULL) {
3837                 return;
3838         }
3839
3840         dm->devicename = talloc_strndup(dm, printername,
3841                                         MIN(strlen(printername), 31));
3842 }
3843
3844 /********************************************************************
3845  * construct_printer_info_0
3846  * fill a printer_info_0 struct
3847  ********************************************************************/
3848
3849 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3850                                       const struct auth_session_info *session_info,
3851                                       struct messaging_context *msg_ctx,
3852                                       struct spoolss_PrinterInfo2 *info2,
3853                                       const char *servername,
3854                                       struct spoolss_PrinterInfo0 *r,
3855                                       int snum)
3856 {
3857         int count;
3858         struct printer_session_counter *session_counter;
3859         struct timeval setuptime;
3860         print_status_struct status;
3861         WERROR result;
3862
3863         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3864         if (!W_ERROR_IS_OK(result)) {
3865                 return result;
3866         }
3867
3868         if (servername) {
3869                 r->servername = talloc_strdup(mem_ctx, servername);
3870                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3871         } else {
3872                 r->servername = NULL;
3873         }
3874
3875         count = print_queue_length(msg_ctx, snum, &status);
3876
3877         /* check if we already have a counter for this printer */
3878         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3879                 if (session_counter->snum == snum)
3880                         break;
3881         }
3882
3883         /* it's the first time, add it to the list */
3884         if (session_counter == NULL) {
3885                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3886                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3887                 session_counter->snum           = snum;
3888                 session_counter->counter        = 0;
3889                 DLIST_ADD(counter_list, session_counter);
3890         }
3891
3892         /* increment it */
3893         session_counter->counter++;
3894
3895         r->cjobs                        = count;
3896         r->total_jobs                   = 0;
3897         r->total_bytes                  = 0;
3898
3899         get_startup_time(&setuptime);
3900         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3901
3902         /* JFM:
3903          * the global_counter should be stored in a TDB as it's common to all the clients
3904          * and should be zeroed on samba startup
3905          */
3906         r->global_counter               = session_counter->counter;
3907         r->total_pages                  = 0;
3908         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3909         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3910         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3911         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3912         r->spooling                     = 0;
3913         r->max_spooling                 = 0;
3914         r->session_counter              = session_counter->counter;
3915         r->num_error_out_of_paper       = 0x0;
3916         r->num_error_not_ready          = 0x0;          /* number of print failure */
3917         r->job_error                    = 0x0;
3918         r->number_of_processors         = 0x1;
3919         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3920         r->high_part_total_bytes        = 0x0;
3921
3922         /* ChangeID in milliseconds*/
3923         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3924                                     info2->sharename, &r->change_id);
3925
3926         r->last_error                   = WERR_OK;
3927         r->status                       = nt_printq_status(status.status);
3928         r->enumerate_network_printers   = 0x0;
3929         r->c_setprinter                 = 0x0;
3930         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3931         r->processor_level              = 0x6;          /* 6  ???*/
3932         r->ref_ic                       = 0;
3933         r->reserved2                    = 0;
3934         r->reserved3                    = 0;
3935
3936         return WERR_OK;
3937 }
3938
3939
3940 /********************************************************************
3941  * construct_printer_info1
3942  * fill a spoolss_PrinterInfo1 struct
3943 ********************************************************************/
3944
3945 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3946                                       const struct spoolss_PrinterInfo2 *info2,
3947                                       uint32_t flags,
3948                                       const char *servername,
3949                                       struct spoolss_PrinterInfo1 *r,
3950                                       int snum)
3951 {
3952         WERROR result;
3953
3954         r->flags                = flags;
3955
3956         if (info2->comment == NULL || info2->comment[0] == '\0') {
3957                 r->comment      = lp_comment(mem_ctx, snum);
3958         } else {
3959                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3960         }
3961         W_ERROR_HAVE_NO_MEMORY(r->comment);
3962
3963         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3964         if (!W_ERROR_IS_OK(result)) {
3965                 return result;
3966         }
3967
3968         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3969                                                   r->name,
3970                                                   info2->drivername,
3971                                                   r->comment);
3972         W_ERROR_HAVE_NO_MEMORY(r->description);
3973
3974         return WERR_OK;
3975 }
3976
3977 /********************************************************************
3978  * construct_printer_info2
3979  * fill a spoolss_PrinterInfo2 struct
3980 ********************************************************************/
3981
3982 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3983                                       struct messaging_context *msg_ctx,
3984                                       const struct spoolss_PrinterInfo2 *info2,
3985                                       const char *servername,
3986                                       struct spoolss_PrinterInfo2 *r,
3987                                       int snum)
3988 {
3989         int count;
3990         print_status_struct status;
3991         WERROR result;
3992
3993         count = print_queue_length(msg_ctx, snum, &status);
3994
3995         if (servername) {
3996                 r->servername           = talloc_strdup(mem_ctx, servername);
3997                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3998         } else {
3999                 r->servername           = NULL;
4000         }
4001
4002         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4003         if (!W_ERROR_IS_OK(result)) {
4004                 return result;
4005         }
4006
4007         r->sharename            = lp_servicename(mem_ctx, snum);
4008         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4009         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4010         W_ERROR_HAVE_NO_MEMORY(r->portname);
4011         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4012         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4013
4014         if (info2->comment[0] == '\0') {
4015                 r->comment      = lp_comment(mem_ctx, snum);
4016         } else {
4017                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4018         }
4019         W_ERROR_HAVE_NO_MEMORY(r->comment);
4020
4021         r->location     = talloc_strdup(mem_ctx, info2->location);
4022         if (info2->location[0] == '\0') {
4023                 const char *loc = NULL;
4024                 NTSTATUS nt_status;
4025
4026                 nt_status = printer_list_get_printer(mem_ctx,
4027                                                      info2->sharename,
4028                                                      NULL,
4029                                                      &loc,
4030                                                      NULL);
4031                 if (NT_STATUS_IS_OK(nt_status)) {
4032                         if (loc != NULL) {
4033                                 r->location = talloc_strdup(mem_ctx, loc);
4034                         }
4035                 }
4036         }
4037         W_ERROR_HAVE_NO_MEMORY(r->location);
4038
4039         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4040         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4041         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4042         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4043         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4044         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4045         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4046         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4047
4048         r->attributes           = info2->attributes;
4049
4050         r->priority             = info2->priority;
4051         r->defaultpriority      = info2->defaultpriority;
4052         r->starttime            = info2->starttime;
4053         r->untiltime            = info2->untiltime;
4054         r->status               = nt_printq_status(status.status);
4055         r->cjobs                = count;
4056         r->averageppm           = info2->averageppm;
4057
4058         if (info2->devmode != NULL) {
4059                 result = copy_devicemode(mem_ctx,
4060                                          info2->devmode,
4061                                          &r->devmode);
4062                 if (!W_ERROR_IS_OK(result)) {
4063                         return result;
4064                 }
4065         } else if (lp_default_devmode(snum)) {
4066                 result = spoolss_create_default_devmode(mem_ctx,
4067                                                         info2->printername,
4068                                                         &r->devmode);
4069                 if (!W_ERROR_IS_OK(result)) {
4070                         return result;
4071                 }
4072         } else {
4073                 r->devmode = NULL;
4074                 DEBUG(8,("Returning NULL Devicemode!\n"));
4075         }
4076
4077         compose_devicemode_devicename(r->devmode, r->printername);
4078
4079         r->secdesc = NULL;
4080
4081         if (info2->secdesc != NULL) {
4082                 /* don't use talloc_steal() here unless you do a deep steal of all
4083                    the SEC_DESC members */
4084
4085                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4086                 if (r->secdesc == NULL) {
4087                         return WERR_NOMEM;
4088                 }
4089         }
4090
4091         return WERR_OK;
4092 }
4093
4094 /********************************************************************
4095  * construct_printer_info3
4096  * fill a spoolss_PrinterInfo3 struct
4097  ********************************************************************/
4098
4099 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4100                                       const struct spoolss_PrinterInfo2 *info2,
4101                                       const char *servername,
4102                                       struct spoolss_PrinterInfo3 *r,
4103                                       int snum)
4104 {
4105         /* These are the components of the SD we are returning. */
4106
4107         if (info2->secdesc != NULL) {
4108                 /* don't use talloc_steal() here unless you do a deep steal of all
4109                    the SEC_DESC members */
4110
4111                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4112                 if (r->secdesc == NULL) {
4113                         return WERR_NOMEM;
4114                 }
4115         }
4116
4117         return WERR_OK;
4118 }
4119
4120 /********************************************************************
4121  * construct_printer_info4
4122  * fill a spoolss_PrinterInfo4 struct
4123  ********************************************************************/
4124
4125 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4126                                       const struct spoolss_PrinterInfo2 *info2,
4127                                       const char *servername,
4128                                       struct spoolss_PrinterInfo4 *r,
4129                                       int snum)
4130 {
4131         WERROR result;
4132
4133         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4134         if (!W_ERROR_IS_OK(result)) {
4135                 return result;
4136         }
4137
4138         if (servername) {
4139                 r->servername   = talloc_strdup(mem_ctx, servername);
4140                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4141         } else {
4142                 r->servername = NULL;
4143         }
4144
4145         r->attributes   = info2->attributes;
4146
4147         return WERR_OK;
4148 }
4149
4150 /********************************************************************
4151  * construct_printer_info5
4152  * fill a spoolss_PrinterInfo5 struct
4153  ********************************************************************/
4154
4155 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4156                                       const struct spoolss_PrinterInfo2 *info2,
4157                                       const char *servername,
4158                                       struct spoolss_PrinterInfo5 *r,
4159                                       int snum)
4160 {
4161         WERROR result;
4162
4163         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4164         if (!W_ERROR_IS_OK(result)) {
4165                 return result;
4166         }
4167
4168         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4169         W_ERROR_HAVE_NO_MEMORY(r->portname);
4170
4171         r->attributes   = info2->attributes;
4172
4173         /* these two are not used by NT+ according to MSDN */
4174         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4175         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4176
4177         return WERR_OK;
4178 }
4179
4180 /********************************************************************
4181  * construct_printer_info_6
4182  * fill a spoolss_PrinterInfo6 struct
4183  ********************************************************************/
4184
4185 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4186                                       struct messaging_context *msg_ctx,
4187                                       const struct spoolss_PrinterInfo2 *info2,
4188                                       const char *servername,
4189                                       struct spoolss_PrinterInfo6 *r,
4190                                       int snum)
4191 {
4192         print_status_struct status;
4193
4194         print_queue_length(msg_ctx, snum, &status);
4195
4196         r->status = nt_printq_status(status.status);
4197
4198         return WERR_OK;
4199 }
4200
4201 /********************************************************************
4202  * construct_printer_info7
4203  * fill a spoolss_PrinterInfo7 struct
4204  ********************************************************************/
4205
4206 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4207                                       struct messaging_context *msg_ctx,
4208                                       const char *servername,
4209                                       struct spoolss_PrinterInfo7 *r,
4210                                       int snum)
4211 {
4212         const struct auth_session_info *session_info;
4213         char *printer;
4214         WERROR werr;
4215         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4216         if (tmp_ctx == NULL) {
4217                 return WERR_NOMEM;
4218         }
4219
4220         session_info = get_session_info_system();
4221         SMB_ASSERT(session_info != NULL);
4222
4223         printer = lp_servicename(tmp_ctx, snum);
4224         if (printer == NULL) {
4225                 DEBUG(0, ("invalid printer snum %d\n", snum));
4226                 werr = WERR_INVALID_PARAM;
4227                 goto out_tmp_free;
4228         }
4229
4230         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4231                                  servername, printer, NULL)) {
4232                 struct GUID guid;
4233                 struct GUID_txt_buf guid_txt;
4234                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4235                                            printer, &guid);
4236                 if (!W_ERROR_IS_OK(werr)) {
4237                         /*
4238                          * If we do not have a GUID entry in the registry, then
4239                          * try to retrieve it from AD and store it now.
4240                          */
4241                         werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4242                                                         &guid);
4243                         if (!W_ERROR_IS_OK(werr)) {
4244                                 DEBUG(1, ("Failed to retrieve GUID for "
4245                                           "printer [%s] from AD - "
4246                                           "Is the the printer still "
4247                                           "published ?\n", printer));
4248                                 goto out_tmp_free;
4249                         }
4250
4251                         werr = nt_printer_guid_store(msg_ctx, printer, guid);
4252                         if (!W_ERROR_IS_OK(werr)) {
4253                                 DEBUG(3, ("failed to store printer %s guid\n",
4254                                           printer));
4255                         }
4256                 }
4257                 r->guid = talloc_strdup_upper(mem_ctx,
4258                                              GUID_buf_string(&guid, &guid_txt));
4259                 r->action = DSPRINT_PUBLISH;
4260         } else {
4261                 r->guid = talloc_strdup(mem_ctx, "");
4262                 r->action = DSPRINT_UNPUBLISH;
4263         }
4264         if (r->guid == NULL) {
4265                 werr = WERR_NOMEM;
4266                 goto out_tmp_free;
4267         }
4268
4269         werr = WERR_OK;
4270 out_tmp_free:
4271         talloc_free(tmp_ctx);
4272         return werr;
4273 }
4274
4275 /********************************************************************
4276  * construct_printer_info8
4277  * fill a spoolss_PrinterInfo8 struct
4278  ********************************************************************/
4279
4280 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4281                                       const struct spoolss_PrinterInfo2 *info2,
4282                                       const char *servername,
4283                                       struct spoolss_DeviceModeInfo *r,
4284                                       int snum)
4285 {
4286         WERROR result;
4287         const char *printername;
4288
4289         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4290         if (!W_ERROR_IS_OK(result)) {
4291                 return result;
4292         }
4293
4294         if (info2->devmode != NULL) {
4295                 result = copy_devicemode(mem_ctx,
4296                                          info2->devmode,
4297                                          &r->devmode);
4298                 if (!W_ERROR_IS_OK(result)) {
4299                         return result;
4300                 }
4301         } else if (lp_default_devmode(snum)) {
4302                 result = spoolss_create_default_devmode(mem_ctx,
4303                                                         info2->printername,
4304                                                         &r->devmode);
4305                 if (!W_ERROR_IS_OK(result)) {
4306                         return result;
4307                 }
4308         } else {
4309                 r->devmode = NULL;
4310                 DEBUG(8,("Returning NULL Devicemode!\n"));
4311         }
4312
4313         compose_devicemode_devicename(r->devmode, printername);
4314
4315         return WERR_OK;
4316 }
4317
4318 /********************************************************************
4319  Spoolss_enumprinters.
4320 ********************************************************************/
4321
4322 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4323                                            const struct auth_session_info *session_info,
4324                                            struct messaging_context *msg_ctx,
4325                                            const char *servername,
4326                                            uint32_t level,
4327                                            uint32_t flags,
4328                                            union spoolss_PrinterInfo **info_p,
4329                                            uint32_t *count_p)
4330 {
4331         int snum;
4332         int n_services;
4333         union spoolss_PrinterInfo *info = NULL;
4334         uint32_t count = 0;
4335         WERROR result = WERR_OK;
4336         struct dcerpc_binding_handle *b = NULL;
4337         TALLOC_CTX *tmp_ctx = NULL;
4338
4339         tmp_ctx = talloc_new(mem_ctx);
4340         if (!tmp_ctx) {
4341                 return WERR_NOMEM;
4342         }
4343
4344         /*
4345          * printer shares are updated on client enumeration. The background
4346          * printer process updates printer_list.tdb at regular intervals.
4347          */
4348         become_root();
4349         delete_and_reload_printers(server_event_context(), msg_ctx);
4350         unbecome_root();
4351
4352         n_services = lp_numservices();
4353         *count_p = 0;
4354         *info_p = NULL;
4355
4356         for (snum = 0; snum < n_services; snum++) {
4357
4358                 const char *printer;
4359                 struct spoolss_PrinterInfo2 *info2;
4360
4361                 if (!snum_is_shared_printer(snum)) {
4362                         continue;
4363                 }
4364
4365                 printer = lp_const_servicename(snum);
4366
4367                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4368                         printer, snum));
4369
4370                 if (b == NULL) {
4371                         result = winreg_printer_binding_handle(tmp_ctx,
4372                                                                session_info,
4373                                                                msg_ctx,
4374                                                                &b);
4375                         if (!W_ERROR_IS_OK(result)) {
4376                                 goto out;
4377                         }
4378                 }
4379
4380                 result = winreg_create_printer(tmp_ctx, b,
4381                                                printer);
4382                 if (!W_ERROR_IS_OK(result)) {
4383                         goto out;
4384                 }
4385
4386                 info = talloc_realloc(tmp_ctx, info,
4387                                             union spoolss_PrinterInfo,
4388                                             count + 1);
4389                 if (!info) {
4390                         result = WERR_NOMEM;
4391                         goto out;
4392                 }
4393
4394                 result = winreg_get_printer(tmp_ctx, b,
4395                                             printer, &info2);
4396                 if (!W_ERROR_IS_OK(result)) {
4397                         goto out;
4398                 }
4399
4400                 switch (level) {
4401                 case 0:
4402                         result = construct_printer_info0(info, session_info,
4403                                                          msg_ctx, info2,
4404                                                          servername,
4405                                                          &info[count].info0, snum);
4406                         break;
4407                 case 1:
4408                         result = construct_printer_info1(info, info2, flags,
4409                                                          servername,
4410                                                          &info[count].info1, snum);
4411                         break;
4412                 case 2:
4413                         result = construct_printer_info2(info, msg_ctx, info2,
4414                                                          servername,
4415                                                          &info[count].info2, snum);
4416                         break;
4417                 case 4:
4418                         result = construct_printer_info4(info, info2,
4419                                                          servername,
4420                                                          &info[count].info4, snum);
4421                         break;
4422                 case 5:
4423                         result = construct_printer_info5(info, info2,
4424                                                          servername,
4425                                                          &info[count].info5, snum);
4426                         break;
4427
4428                 default:
4429                         result = WERR_UNKNOWN_LEVEL;
4430                         goto out;
4431                 }
4432
4433                 if (!W_ERROR_IS_OK(result)) {
4434                         goto out;
4435                 }
4436
4437                 count++;
4438         }
4439
4440 out:
4441         if (W_ERROR_IS_OK(result)) {
4442                 *info_p = talloc_move(mem_ctx, &info);
4443                 *count_p = count;
4444         }
4445
4446         talloc_free(tmp_ctx);
4447
4448         return result;
4449 }
4450
4451 /********************************************************************
4452  * handle enumeration of printers at level 0
4453  ********************************************************************/
4454
4455 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4456                                   const struct auth_session_info *session_info,
4457                                   struct messaging_context *msg_ctx,
4458                                   uint32_t flags,
4459                                   const char *servername,
4460                                   union spoolss_PrinterInfo **info,
4461                                   uint32_t *count)
4462 {
4463         DEBUG(4,("enum_all_printers_info_0\n"));
4464
4465         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4466                                             servername, 0, flags, info, count);
4467 }
4468
4469
4470 /********************************************************************
4471 ********************************************************************/
4472
4473 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4474                                        const struct auth_session_info *session_info,
4475                                        struct messaging_context *msg_ctx,
4476                                        const char *servername,
4477                                        uint32_t flags,
4478                                        union spoolss_PrinterInfo **info,
4479                                        uint32_t *count)
4480 {
4481         DEBUG(4,("enum_all_printers_info_1\n"));
4482
4483         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4484                                             servername, 1, flags, info, count);
4485 }
4486
4487 /********************************************************************
4488  enum_all_printers_info_1_local.
4489 *********************************************************************/
4490
4491 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4492                                              const struct auth_session_info *session_info,
4493                                              struct messaging_context *msg_ctx,
4494                                              const char *servername,
4495                                              union spoolss_PrinterInfo **info,
4496                                              uint32_t *count)
4497 {
4498         DEBUG(4,("enum_all_printers_info_1_local\n"));
4499
4500         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4501                                         servername, PRINTER_ENUM_ICON8, info, count);
4502 }
4503
4504 /********************************************************************
4505  enum_all_printers_info_1_name.
4506 *********************************************************************/
4507
4508 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4509                                             const struct auth_session_info *session_info,
4510                                             struct messaging_context *msg_ctx,
4511                                             const char *servername,
4512                                             union spoolss_PrinterInfo **info,
4513                                             uint32_t *count)
4514 {
4515         const char *s = servername;
4516
4517         DEBUG(4,("enum_all_printers_info_1_name\n"));
4518
4519         if (servername != NULL &&
4520             (servername[0] == '\\') && (servername[1] == '\\')) {
4521                 s = servername + 2;
4522         }
4523
4524         if (!is_myname_or_ipaddr(s)) {
4525                 return WERR_INVALID_NAME;
4526         }
4527
4528         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4529                                         servername, PRINTER_ENUM_ICON8, info, count);
4530 }
4531
4532 /********************************************************************
4533  enum_all_printers_info_1_network.
4534 *********************************************************************/
4535
4536 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4537                                                const struct auth_session_info *session_info,
4538                                                struct messaging_context *msg_ctx,
4539                                                const char *servername,
4540                                                union spoolss_PrinterInfo **info,
4541                                                uint32_t *count)
4542 {
4543         const char *s = servername;
4544
4545         DEBUG(4,("enum_all_printers_info_1_network\n"));
4546
4547         /* If we respond to a enum_printers level 1 on our name with flags
4548            set to PRINTER_ENUM_REMOTE with a list of printers then these
4549            printers incorrectly appear in the APW browse list.
4550            Specifically the printers for the server appear at the workgroup
4551            level where all the other servers in the domain are
4552            listed. Windows responds to this call with a
4553            WERR_CAN_NOT_COMPLETE so we should do the same. */
4554
4555         if (servername != NULL &&
4556             (servername[0] == '\\') && (servername[1] == '\\')) {
4557                  s = servername + 2;
4558         }
4559
4560         if (is_myname_or_ipaddr(s)) {
4561                  return WERR_CAN_NOT_COMPLETE;
4562         }
4563
4564         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4565                                         servername, PRINTER_ENUM_NAME, info, count);
4566 }
4567
4568 /********************************************************************
4569  * api_spoolss_enumprinters
4570  *
4571  * called from api_spoolss_enumprinters (see this to understand)
4572  ********************************************************************/
4573
4574 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4575                                        const struct auth_session_info *session_info,
4576                                        struct messaging_context *msg_ctx,
4577                                        const char *servername,
4578                                        union spoolss_PrinterInfo **info,
4579                                        uint32_t *count)
4580 {
4581         DEBUG(4,("enum_all_printers_info_2\n"));
4582
4583         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4584                                             servername, 2, 0, info, count);
4585 }
4586
4587 /********************************************************************
4588  * handle enumeration of printers at level 1
4589  ********************************************************************/
4590
4591 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4592                                   const struct auth_session_info *session_info,
4593                                   struct messaging_context *msg_ctx,
4594                                   uint32_t flags,
4595                                   const char *servername,
4596                                   union spoolss_PrinterInfo **info,
4597                                   uint32_t *count)
4598 {
4599         /* Not all the flags are equals */
4600
4601         if (flags & PRINTER_ENUM_LOCAL) {
4602                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4603                                                       msg_ctx, servername, info, count);
4604         }
4605
4606         if (flags & PRINTER_ENUM_NAME) {
4607                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4608                                                      msg_ctx, servername, info,
4609                                                      count);
4610         }
4611
4612         if (flags & PRINTER_ENUM_NETWORK) {
4613                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4614                                                         msg_ctx, servername, info,
4615                                                         count);
4616         }
4617
4618         return WERR_OK; /* NT4sp5 does that */
4619 }
4620
4621 /********************************************************************
4622  * handle enumeration of printers at level 2
4623  ********************************************************************/
4624
4625 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4626                                   const struct auth_session_info *session_info,
4627                                   struct messaging_context *msg_ctx,
4628                                   uint32_t flags,
4629                                   const char *servername,
4630                                   union spoolss_PrinterInfo **info,
4631                                   uint32_t *count)
4632 {
4633         if (flags & PRINTER_ENUM_LOCAL) {
4634
4635                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4636                                                 servername,
4637                                                 info, count);
4638         }
4639
4640         if (flags & PRINTER_ENUM_NAME) {
4641                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4642                         return WERR_INVALID_NAME;
4643                 }
4644
4645                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4646                                                 servername,
4647                                                 info, count);
4648         }
4649
4650         if (flags & PRINTER_ENUM_REMOTE) {
4651                 return WERR_UNKNOWN_LEVEL;
4652         }
4653
4654         return WERR_OK;
4655 }
4656
4657 /********************************************************************
4658  * handle enumeration of printers at level 4
4659  ********************************************************************/
4660
4661 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4662                                   const struct auth_session_info *session_info,
4663                                   struct messaging_context *msg_ctx,
4664                                   uint32_t flags,
4665                                   const char *servername,
4666                                   union spoolss_PrinterInfo **info,
4667                                   uint32_t *count)
4668 {
4669         DEBUG(4,("enum_all_printers_info_4\n"));
4670
4671         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4672                                             servername, 4, flags, info, count);
4673 }
4674
4675
4676 /********************************************************************
4677  * handle enumeration of printers at level 5
4678  ********************************************************************/
4679
4680 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4681                                   const struct auth_session_info *session_info,
4682                                   struct messaging_context *msg_ctx,
4683                                   uint32_t flags,
4684                                   const char *servername,
4685                                   union spoolss_PrinterInfo **info,
4686                                   uint32_t *count)
4687 {
4688         DEBUG(4,("enum_all_printers_info_5\n"));
4689
4690         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4691                                             servername, 5, flags, info, count);
4692 }
4693
4694 /****************************************************************
4695  _spoolss_EnumPrinters
4696 ****************************************************************/
4697
4698 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4699                              struct spoolss_EnumPrinters *r)
4700 {
4701         const struct auth_session_info *session_info = get_session_info_system();
4702         WERROR result;
4703
4704         /* that's an [in out] buffer */
4705
4706         if (!r->in.buffer && (r->in.offered != 0)) {
4707                 return WERR_INVALID_PARAM;
4708         }
4709
4710         DEBUG(4,("_spoolss_EnumPrinters\n"));
4711
4712         *r->out.needed = 0;
4713         *r->out.count = 0;
4714         *r->out.info = NULL;
4715
4716         /*
4717          * Level 1:
4718          *          flags==PRINTER_ENUM_NAME
4719          *           if name=="" then enumerates all printers
4720          *           if name!="" then enumerate the printer
4721          *          flags==PRINTER_ENUM_REMOTE
4722          *          name is NULL, enumerate printers
4723          * Level 2: name!="" enumerates printers, name can't be NULL
4724          * Level 3: doesn't exist
4725          * Level 4: does a local registry lookup
4726          * Level 5: same as Level 2
4727          */
4728
4729         if (r->in.server && r->in.server[0] == '\0') {
4730                 r->in.server = NULL;
4731         }
4732
4733         switch (r->in.level) {
4734         case 0:
4735                 result = enumprinters_level0(p->mem_ctx, session_info,
4736                                              p->msg_ctx, r->in.flags,
4737                                              r->in.server,
4738                                              r->out.info, r->out.count);
4739                 break;
4740         case 1:
4741                 result = enumprinters_level1(p->mem_ctx, session_info,
4742                                              p->msg_ctx, r->in.flags,
4743                                              r->in.server,
4744                                              r->out.info, r->out.count);
4745                 break;
4746         case 2:
4747                 result = enumprinters_level2(p->mem_ctx, session_info,
4748                                              p->msg_ctx, r->in.flags,
4749                                              r->in.server,
4750                                              r->out.info, r->out.count);
4751                 break;
4752         case 4:
4753                 result = enumprinters_level4(p->mem_ctx, session_info,
4754                                              p->msg_ctx, r->in.flags,
4755                                              r->in.server,
4756                                              r->out.info, r->out.count);
4757                 break;
4758         case 5:
4759                 result = enumprinters_level5(p->mem_ctx, session_info,
4760                                              p->msg_ctx, r->in.flags,
4761                                              r->in.server,
4762                                              r->out.info, r->out.count);
4763                 break;
4764         default:
4765                 return WERR_UNKNOWN_LEVEL;
4766         }
4767
4768         if (!W_ERROR_IS_OK(result)) {
4769                 return result;
4770         }
4771
4772         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4773                                                      spoolss_EnumPrinters,
4774                                                      *r->out.info, r->in.level,
4775                                                      *r->out.count);
4776         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4777         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4778
4779         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4780 }
4781
4782 /****************************************************************
4783  _spoolss_GetPrinter
4784 ****************************************************************/
4785
4786 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4787                            struct spoolss_GetPrinter *r)
4788 {
4789         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4790         struct spoolss_PrinterInfo2 *info2 = NULL;
4791         WERROR result = WERR_OK;
4792         int snum;
4793
4794         /* that's an [in out] buffer */
4795
4796         if (!r->in.buffer && (r->in.offered != 0)) {
4797                 result = WERR_INVALID_PARAM;
4798                 goto err_info_free;
4799         }
4800
4801         *r->out.needed = 0;
4802
4803         if (Printer == NULL) {
4804                 result = WERR_BADFID;
4805                 goto err_info_free;
4806         }
4807
4808         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4809                 result = WERR_BADFID;
4810                 goto err_info_free;
4811         }
4812
4813         result = winreg_get_printer_internal(p->mem_ctx,
4814                                     get_session_info_system(),
4815                                     p->msg_ctx,
4816                                     lp_const_servicename(snum),
4817                                     &info2);
4818         if (!W_ERROR_IS_OK(result)) {
4819                 goto err_info_free;
4820         }
4821
4822         switch (r->in.level) {
4823         case 0:
4824                 result = construct_printer_info0(p->mem_ctx,
4825                                                  get_session_info_system(),
4826                                                  p->msg_ctx,
4827                                                  info2,
4828                                                  Printer->servername,
4829                                                  &r->out.info->info0,
4830                                                  snum);
4831                 break;
4832         case 1:
4833                 result = construct_printer_info1(p->mem_ctx, info2,
4834                                                  PRINTER_ENUM_ICON8,
4835                                                  Printer->servername,
4836                                                  &r->out.info->info1, snum);
4837                 break;
4838         case 2:
4839                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4840                                                  Printer->servername,
4841                                                  &r->out.info->info2, snum);
4842                 break;
4843         case 3:
4844                 result = construct_printer_info3(p->mem_ctx, info2,
4845                                                  Printer->servername,
4846                                                  &r->out.info->info3, snum);
4847                 break;
4848         case 4:
4849                 result = construct_printer_info4(p->mem_ctx, info2,
4850                                                  Printer->servername,
4851                                                  &r->out.info->info4, snum);
4852                 break;
4853         case 5:
4854                 result = construct_printer_info5(p->mem_ctx, info2,
4855                                                  Printer->servername,
4856                                                  &r->out.info->info5, snum);
4857                 break;
4858         case 6:
4859                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4860                                                  Printer->servername,
4861                                                  &r->out.info->info6, snum);
4862                 break;
4863         case 7:
4864                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4865                                                  Printer->servername,
4866                                                  &r->out.info->info7, snum);
4867                 break;
4868         case 8:
4869                 result = construct_printer_info8(p->mem_ctx, info2,
4870                                                  Printer->servername,
4871                                                  &r->out.info->info8, snum);
4872                 break;
4873         default:
4874                 result = WERR_UNKNOWN_LEVEL;
4875                 break;
4876         }
4877         TALLOC_FREE(info2);
4878
4879         if (!W_ERROR_IS_OK(result)) {
4880                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4881                           r->in.level, win_errstr(result)));
4882                 goto err_info_free;
4883         }
4884
4885         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4886                                                r->out.info, r->in.level);
4887         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4888
4889         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4890
4891 err_info_free:
4892         TALLOC_FREE(r->out.info);
4893         return result;
4894 }
4895
4896 /********************************************************************
4897  ********************************************************************/
4898
4899 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4900         do { \
4901                 if (in && strlen(in)) { \
4902                         out = talloc_strdup(mem_ctx, in); \
4903                 } else { \
4904                         out = talloc_strdup(mem_ctx, ""); \
4905                 } \
4906                 W_ERROR_HAVE_NO_MEMORY(out); \
4907         } while (0);
4908
4909 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4910         do { \
4911                 if (in && strlen(in)) { \
4912                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4913                 } else { \
4914                         out = talloc_strdup(mem_ctx, ""); \
4915                 } \
4916                 W_ERROR_HAVE_NO_MEMORY(out); \
4917         } while (0);
4918
4919 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4920                                                   const char **string_array,
4921                                                   const char ***presult,
4922                                                   const char *cservername,
4923                                                   const char *arch,
4924                                                   int version)
4925 {
4926         int i;
4927         size_t num_strings = 0;
4928         const char **array = NULL;
4929
4930         if (string_array == NULL) {
4931                 return WERR_INVALID_PARAMETER;
4932         }
4933
4934         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4935                 const char *str = NULL;
4936
4937                 if (cservername == NULL || arch == NULL) {
4938                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4939                 } else {
4940                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4941                 }
4942
4943                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4944                         TALLOC_FREE(array);
4945                         return WERR_NOMEM;
4946                 }
4947         }
4948
4949         if (i > 0) {
4950                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4951                              &array, &num_strings);
4952         }
4953
4954         if (presult != NULL) {
4955                 *presult = array;
4956         } else {
4957                 talloc_free(array);
4958         }
4959
4960         return WERR_OK;
4961 }
4962
4963 /********************************************************************
4964  * fill a spoolss_DriverInfo1 struct
4965  ********************************************************************/
4966
4967 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4968                                         struct spoolss_DriverInfo1 *r,
4969                                         const struct spoolss_DriverInfo8 *driver,
4970                                         const char *servername)
4971 {
4972         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4973         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4974
4975         return WERR_OK;
4976 }
4977
4978 /********************************************************************
4979  * fill a spoolss_DriverInfo2 struct
4980  ********************************************************************/
4981
4982 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4983                                         struct spoolss_DriverInfo2 *r,
4984                                         const struct spoolss_DriverInfo8 *driver,
4985                                         const char *servername)
4986
4987 {
4988         const char *cservername = canon_servername(servername);
4989
4990         r->version              = driver->version;
4991
4992         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4993         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4994         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4995         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4996
4997         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4998                                driver->architecture,
4999                                driver->version,
5000                                driver->driver_path,
5001                                r->driver_path);
5002
5003         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5004                                driver->architecture,
5005                                driver->version,
5006                                driver->data_file,
5007                                r->data_file);
5008
5009         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5010                                driver->architecture,
5011                                driver->version,
5012                                driver->config_file,
5013                                r->config_file);
5014
5015         return WERR_OK;
5016 }
5017
5018 /********************************************************************
5019  * fill a spoolss_DriverInfo3 struct
5020  ********************************************************************/
5021
5022 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5023                                         struct spoolss_DriverInfo3 *r,
5024                                         const struct spoolss_DriverInfo8 *driver,
5025                                         const char *servername)
5026 {
5027         const char *cservername = canon_servername(servername);
5028
5029         r->version              = driver->version;
5030
5031         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5032         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5033         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5034         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5035
5036         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5037                                driver->architecture,
5038                                driver->version,
5039                                driver->driver_path,
5040                                r->driver_path);
5041
5042         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5043                                driver->architecture,
5044                                driver->version,
5045                                driver->data_file,
5046                                r->data_file);
5047
5048         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5049                                driver->architecture,
5050                                driver->version,
5051                                driver->config_file,
5052                                r->config_file);
5053
5054         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5055                                driver->architecture,
5056                                driver->version,
5057                                driver->help_file,
5058                                r->help_file);
5059
5060         FILL_DRIVER_STRING(mem_ctx,
5061                            driver->monitor_name,
5062                            r->monitor_name);
5063
5064         FILL_DRIVER_STRING(mem_ctx,
5065                            driver->default_datatype,
5066                            r->default_datatype);
5067
5068         return string_array_from_driver_info(mem_ctx,
5069                                              driver->dependent_files,
5070                                              &r->dependent_files,
5071                                              cservername,
5072                                              driver->architecture,
5073                                              driver->version);
5074 }
5075
5076 /********************************************************************
5077  * fill a spoolss_DriverInfo4 struct
5078  ********************************************************************/
5079
5080 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5081                                         struct spoolss_DriverInfo4 *r,
5082                                         const struct spoolss_DriverInfo8 *driver,
5083                                         const char *servername)
5084 {
5085         const char *cservername = canon_servername(servername);
5086         WERROR result;
5087
5088         r->version              = driver->version;
5089
5090         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5091         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5092         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5093         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5094
5095         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5096                                driver->architecture,
5097                                driver->version,
5098                                driver->driver_path,
5099                                r->driver_path);
5100
5101         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5102                                driver->architecture,
5103                                driver->version,
5104                                driver->data_file,
5105                                r->data_file);
5106
5107         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5108                                driver->architecture,
5109                                driver->version,
5110                                driver->config_file,
5111                                r->config_file);
5112
5113         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5114                                driver->architecture,
5115                                driver->version,
5116                                driver->help_file,
5117                                r->help_file);
5118
5119         result = string_array_from_driver_info(mem_ctx,
5120                                                driver->dependent_files,
5121                                                &r->dependent_files,
5122                                                cservername,
5123                                                driver->architecture,
5124                                                driver->version);
5125         if (!W_ERROR_IS_OK(result)) {
5126                 return result;
5127         }
5128
5129         FILL_DRIVER_STRING(mem_ctx,
5130                            driver->monitor_name,
5131                            r->monitor_name);
5132
5133         FILL_DRIVER_STRING(mem_ctx,
5134                            driver->default_datatype,
5135                            r->default_datatype);
5136
5137
5138         result = string_array_from_driver_info(mem_ctx,
5139                                                driver->previous_names,
5140                                                &r->previous_names,
5141                                                NULL, NULL, 0);
5142
5143         return result;
5144 }
5145
5146 /********************************************************************
5147  * fill a spoolss_DriverInfo5 struct
5148  ********************************************************************/
5149
5150 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5151                                         struct spoolss_DriverInfo5 *r,
5152                                         const struct spoolss_DriverInfo8 *driver,
5153                                         const char *servername)
5154 {
5155         const char *cservername = canon_servername(servername);
5156
5157         r->version              = driver->version;
5158
5159         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5160         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5161         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5162         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5163
5164         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5165                                driver->architecture,
5166                                driver->version,
5167                                driver->driver_path,
5168                                r->driver_path);
5169
5170         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5171                                driver->architecture,
5172                                driver->version,
5173                                driver->data_file,
5174                                r->data_file);
5175
5176         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5177                                driver->architecture,
5178                                driver->version,
5179                                driver->config_file,
5180                                r->config_file);
5181
5182         r->driver_attributes    = 0;
5183         r->config_version       = 0;
5184         r->driver_version       = 0;
5185
5186         return WERR_OK;
5187 }
5188 /********************************************************************
5189  * fill a spoolss_DriverInfo6 struct
5190  ********************************************************************/
5191
5192 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5193                                         struct spoolss_DriverInfo6 *r,
5194                                         const struct spoolss_DriverInfo8 *driver,
5195                                         const char *servername)
5196 {
5197         const char *cservername = canon_servername(servername);
5198         WERROR result;
5199
5200         r->version              = driver->version;
5201
5202         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5203         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5204         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5205         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5206
5207         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5208                                driver->architecture,
5209                                driver->version,
5210                                driver->driver_path,
5211                                r->driver_path);
5212
5213         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5214                                driver->architecture,
5215                                driver->version,
5216                                driver->data_file,
5217                                r->data_file);
5218
5219         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5220                                driver->architecture,
5221                                driver->version,
5222                                driver->config_file,
5223                                r->config_file);
5224
5225         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5226                                driver->architecture,
5227                                driver->version,
5228                                driver->help_file,
5229                                r->help_file);
5230
5231         FILL_DRIVER_STRING(mem_ctx,
5232                            driver->monitor_name,
5233                            r->monitor_name);
5234
5235         FILL_DRIVER_STRING(mem_ctx,
5236                            driver->default_datatype,
5237                            r->default_datatype);
5238
5239         result = string_array_from_driver_info(mem_ctx,
5240                                                driver->dependent_files,
5241                                                &r->dependent_files,
5242                                                cservername,
5243                                                driver->architecture,
5244                                                driver->version);
5245         if (!W_ERROR_IS_OK(result)) {
5246                 return result;
5247         }
5248
5249         result = string_array_from_driver_info(mem_ctx,
5250                                                driver->previous_names,
5251                                                &r->previous_names,
5252                                                NULL, NULL, 0);
5253         if (!W_ERROR_IS_OK(result)) {
5254                 return result;
5255         }
5256
5257         r->driver_date          = driver->driver_date;
5258         r->driver_version       = driver->driver_version;
5259
5260         FILL_DRIVER_STRING(mem_ctx,
5261                            driver->manufacturer_name,
5262                            r->manufacturer_name);
5263         FILL_DRIVER_STRING(mem_ctx,
5264                            driver->manufacturer_url,
5265                            r->manufacturer_url);
5266         FILL_DRIVER_STRING(mem_ctx,
5267                            driver->hardware_id,
5268                            r->hardware_id);
5269         FILL_DRIVER_STRING(mem_ctx,
5270                            driver->provider,
5271                            r->provider);
5272
5273         return WERR_OK;
5274 }
5275
5276 /********************************************************************
5277  * fill a spoolss_DriverInfo8 struct
5278  ********************************************************************/
5279
5280 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5281                                         struct spoolss_DriverInfo8 *r,
5282                                         const struct spoolss_DriverInfo8 *driver,
5283                                         const char *servername)
5284 {
5285         const char *cservername = canon_servername(servername);
5286         WERROR result;
5287
5288         r->version              = driver->version;
5289
5290         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5291         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5292         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5293         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5294
5295         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5296                                driver->architecture,
5297                                driver->version,
5298                                driver->driver_path,
5299                                r->driver_path);
5300
5301         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5302                                driver->architecture,
5303                                driver->version,
5304                                driver->data_file,
5305                                r->data_file);
5306
5307         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5308                                driver->architecture,
5309                                driver->version,
5310                                driver->config_file,
5311                                r->config_file);
5312
5313         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5314                                driver->architecture,
5315                                driver->version,
5316                                driver->help_file,
5317                                r->help_file);
5318
5319         FILL_DRIVER_STRING(mem_ctx,
5320                            driver->monitor_name,
5321                            r->monitor_name);
5322
5323         FILL_DRIVER_STRING(mem_ctx,
5324                            driver->default_datatype,
5325                            r->default_datatype);
5326
5327         result = string_array_from_driver_info(mem_ctx,
5328                                                driver->dependent_files,
5329                                                &r->dependent_files,
5330                                                cservername,
5331                                                driver->architecture,
5332                                                driver->version);
5333         if (!W_ERROR_IS_OK(result)) {
5334                 return result;
5335         }
5336
5337         result = string_array_from_driver_info(mem_ctx,
5338                                                driver->previous_names,
5339                                                &r->previous_names,
5340                                                NULL, NULL, 0);
5341         if (!W_ERROR_IS_OK(result)) {
5342                 return result;
5343         }
5344
5345         r->driver_date          = driver->driver_date;
5346         r->driver_version       = driver->driver_version;
5347
5348         FILL_DRIVER_STRING(mem_ctx,
5349                            driver->manufacturer_name,
5350                            r->manufacturer_name);
5351         FILL_DRIVER_STRING(mem_ctx,
5352                            driver->manufacturer_url,
5353                            r->manufacturer_url);
5354         FILL_DRIVER_STRING(mem_ctx,
5355                            driver->hardware_id,
5356                            r->hardware_id);
5357         FILL_DRIVER_STRING(mem_ctx,
5358                            driver->provider,
5359                            r->provider);
5360
5361         FILL_DRIVER_STRING(mem_ctx,
5362                            driver->print_processor,
5363                            r->print_processor);
5364         FILL_DRIVER_STRING(mem_ctx,
5365                            driver->vendor_setup,
5366                            r->vendor_setup);
5367
5368         result = string_array_from_driver_info(mem_ctx,
5369                                                driver->color_profiles,
5370                                                &r->color_profiles,
5371                                                NULL, NULL, 0);
5372         if (!W_ERROR_IS_OK(result)) {
5373                 return result;
5374         }
5375
5376         FILL_DRIVER_STRING(mem_ctx,
5377                            driver->inf_path,
5378                            r->inf_path);
5379
5380         r->printer_driver_attributes    = driver->printer_driver_attributes;
5381
5382         result = string_array_from_driver_info(mem_ctx,
5383                                                driver->core_driver_dependencies,
5384                                                &r->core_driver_dependencies,
5385                                                NULL, NULL, 0);
5386         if (!W_ERROR_IS_OK(result)) {
5387                 return result;
5388         }
5389
5390         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5391         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5392
5393         return WERR_OK;
5394 }
5395
5396 #if 0 /* disabled until marshalling issues are resolved - gd */
5397 /********************************************************************
5398  ********************************************************************/
5399
5400 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5401                                           struct spoolss_DriverFileInfo *r,
5402                                           const char *cservername,
5403                                           const char *file_name,
5404                                           enum spoolss_DriverFileType file_type,
5405                                           uint32_t file_version)
5406 {
5407         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5408                                           cservername, file_name);
5409         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5410         r->file_type    = file_type;
5411         r->file_version = file_version;
5412
5413         return WERR_OK;
5414 }
5415
5416 /********************************************************************
5417  ********************************************************************/
5418
5419 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5420                                                  const struct spoolss_DriverInfo8 *driver,
5421                                                  const char *cservername,
5422                                                  struct spoolss_DriverFileInfo **info_p,
5423                                                  uint32_t *count_p)
5424 {
5425         struct spoolss_DriverFileInfo *info = NULL;
5426         uint32_t count = 0;
5427         WERROR result;
5428         uint32_t i;
5429
5430         *info_p = NULL;
5431         *count_p = 0;
5432
5433         if (strlen(driver->driver_path)) {
5434                 info = talloc_realloc(mem_ctx, info,
5435                                             struct spoolss_DriverFileInfo,
5436                                             count + 1);
5437                 W_ERROR_HAVE_NO_MEMORY(info);
5438                 result = fill_spoolss_DriverFileInfo(info,
5439                                                      &info[count],
5440                                                      cservername,
5441                                                      driver->driver_path,
5442                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5443                                                      0);
5444                 W_ERROR_NOT_OK_RETURN(result);
5445                 count++;
5446         }
5447
5448         if (strlen(driver->config_file)) {
5449                 info = talloc_realloc(mem_ctx, info,
5450                                             struct spoolss_DriverFileInfo,
5451                                             count + 1);
5452                 W_ERROR_HAVE_NO_MEMORY(info);
5453                 result = fill_spoolss_DriverFileInfo(info,
5454                                                      &info[count],
5455                                                      cservername,
5456                                                      driver->config_file,
5457                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5458                                                      0);
5459                 W_ERROR_NOT_OK_RETURN(result);
5460                 count++;
5461         }
5462
5463         if (strlen(driver->data_file)) {
5464                 info = talloc_realloc(mem_ctx, info,
5465                                             struct spoolss_DriverFileInfo,
5466                                             count + 1);
5467                 W_ERROR_HAVE_NO_MEMORY(info);
5468                 result = fill_spoolss_DriverFileInfo(info,
5469                                                      &info[count],
5470                                                      cservername,
5471                                                      driver->data_file,
5472                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5473                                                      0);
5474                 W_ERROR_NOT_OK_RETURN(result);
5475                 count++;
5476         }
5477
5478         if (strlen(driver->help_file)) {
5479                 info = talloc_realloc(mem_ctx, info,
5480                                             struct spoolss_DriverFileInfo,
5481                                             count + 1);
5482                 W_ERROR_HAVE_NO_MEMORY(info);
5483                 result = fill_spoolss_DriverFileInfo(info,
5484                                                      &info[count],
5485                                                      cservername,
5486                                                      driver->help_file,
5487                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5488                                                      0);
5489                 W_ERROR_NOT_OK_RETURN(result);
5490                 count++;
5491         }
5492
5493         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5494                 info = talloc_realloc(mem_ctx, info,
5495                                             struct spoolss_DriverFileInfo,
5496                                             count + 1);
5497                 W_ERROR_HAVE_NO_MEMORY(info);
5498                 result = fill_spoolss_DriverFileInfo(info,
5499                                                      &info[count],
5500                                                      cservername,
5501                                                      driver->dependent_files[i],
5502                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5503                                                      0);
5504                 W_ERROR_NOT_OK_RETURN(result);
5505                 count++;
5506         }
5507
5508         *info_p = info;
5509         *count_p = count;
5510
5511         return WERR_OK;
5512 }
5513
5514 /********************************************************************
5515  * fill a spoolss_DriverInfo101 struct
5516  ********************************************************************/
5517
5518 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5519                                           struct spoolss_DriverInfo101 *r,
5520                                           const struct spoolss_DriverInfo8 *driver,
5521                                           const char *servername)
5522 {
5523         const char *cservername = canon_servername(servername);
5524         WERROR result;
5525
5526         r->version              = driver->version;
5527
5528         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5529         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5530         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5531         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5532
5533         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5534                                                     cservername,
5535                                                     &r->file_info,
5536                                                     &r->file_count);
5537         if (!W_ERROR_IS_OK(result)) {
5538                 return result;
5539         }
5540
5541         FILL_DRIVER_STRING(mem_ctx,
5542                            driver->monitor_name,
5543                            r->monitor_name);
5544
5545         FILL_DRIVER_STRING(mem_ctx,
5546                            driver->default_datatype,
5547                            r->default_datatype);
5548
5549         result = string_array_from_driver_info(mem_ctx,
5550                                                driver->previous_names,
5551                                                &r->previous_names,
5552                                                NULL, NULL, 0);
5553         if (!W_ERROR_IS_OK(result)) {
5554                 return result;
5555         }
5556
5557         r->driver_date          = driver->driver_date;
5558         r->driver_version       = driver->driver_version;
5559
5560         FILL_DRIVER_STRING(mem_ctx,
5561                            driver->manufacturer_name,
5562                            r->manufacturer_name);
5563         FILL_DRIVER_STRING(mem_ctx,
5564                            driver->manufacturer_url,
5565                            r->manufacturer_url);
5566         FILL_DRIVER_STRING(mem_ctx,
5567                            driver->hardware_id,
5568                            r->hardware_id);
5569         FILL_DRIVER_STRING(mem_ctx,
5570                            driver->provider,
5571                            r->provider);
5572
5573         return WERR_OK;
5574 }
5575 #endif
5576 /********************************************************************
5577  ********************************************************************/
5578
5579 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5580                                                   const struct auth_session_info *session_info,
5581                                                   struct messaging_context *msg_ctx,
5582                                                   uint32_t level,
5583                                                   union spoolss_DriverInfo *r,
5584                                                   int snum,
5585                                                   const char *servername,
5586                                                   const char *architecture,
5587                                                   uint32_t version)
5588 {
5589         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5590         struct spoolss_DriverInfo8 *driver;
5591         WERROR result;
5592         struct dcerpc_binding_handle *b;
5593         TALLOC_CTX *tmp_ctx = NULL;
5594
5595         if (level == 101) {
5596                 return WERR_UNKNOWN_LEVEL;
5597         }
5598
5599         tmp_ctx = talloc_new(mem_ctx);
5600         if (!tmp_ctx) {
5601                 return WERR_NOMEM;
5602         }
5603
5604         result = winreg_printer_binding_handle(tmp_ctx,
5605                                                session_info,
5606                                                msg_ctx,
5607                                                &b);
5608         if (!W_ERROR_IS_OK(result)) {
5609                 goto done;
5610         }
5611
5612         result = winreg_get_printer(tmp_ctx, b,
5613                                     lp_const_servicename(snum),
5614                                     &pinfo2);
5615
5616         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5617                 win_errstr(result)));
5618
5619         if (!W_ERROR_IS_OK(result)) {
5620                 result = WERR_INVALID_PRINTER_NAME;
5621                 goto done;
5622         }
5623
5624         result = winreg_get_driver(tmp_ctx, b,
5625                                    architecture,
5626                                    pinfo2->drivername, version, &driver);
5627
5628         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5629                 win_errstr(result)));
5630
5631         if (!W_ERROR_IS_OK(result)) {
5632                 /*
5633                  * Is this a W2k client ?
5634                  */
5635
5636                 if (version < 3) {
5637                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5638                         goto done;
5639                 }
5640
5641                 /* Yes - try again with a WinNT driver. */
5642                 version = 2;
5643                 result = winreg_get_driver(tmp_ctx, b,
5644                                            architecture,
5645                                            pinfo2->drivername,
5646                                            version, &driver);
5647                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5648                         win_errstr(result)));
5649                 if (!W_ERROR_IS_OK(result)) {
5650                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5651                         goto done;
5652                 }
5653         }
5654
5655         /* these are allocated on mem_ctx and not tmp_ctx because they are
5656          * the 'return value' and need to utlive this call */
5657         switch (level) {
5658         case 1:
5659                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5660                 break;
5661         case 2:
5662                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5663                 break;
5664         case 3:
5665                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5666                 break;
5667         case 4:
5668                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5669                 break;
5670         case 5:
5671                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5672                 break;
5673         case 6:
5674                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5675                 break;
5676         case 8:
5677                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5678                 break;
5679 #if 0 /* disabled until marshalling issues are resolved - gd */
5680         case 101:
5681                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5682                 break;
5683 #endif
5684         default:
5685                 result = WERR_UNKNOWN_LEVEL;
5686                 break;
5687         }
5688
5689 done:
5690         talloc_free(tmp_ctx);
5691         return result;
5692 }
5693
5694 /****************************************************************
5695  _spoolss_GetPrinterDriver2
5696 ****************************************************************/
5697
5698 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5699                                   struct spoolss_GetPrinterDriver2 *r)
5700 {
5701         struct printer_handle *printer;
5702         WERROR result;
5703         uint32_t version = r->in.client_major_version;
5704
5705         int snum;
5706
5707         /* that's an [in out] buffer */
5708
5709         if (!r->in.buffer && (r->in.offered != 0)) {
5710                 result = WERR_INVALID_PARAM;
5711                 goto err_info_free;
5712         }
5713
5714         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5715
5716         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5717                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5718                 result = WERR_INVALID_PRINTER_NAME;
5719                 goto err_info_free;
5720         }
5721
5722         *r->out.needed = 0;
5723         *r->out.server_major_version = 0;
5724         *r->out.server_minor_version = 0;
5725
5726         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5727                 result = WERR_BADFID;
5728                 goto err_info_free;
5729         }
5730
5731         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5732                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5733                         "downgrading to v3\n"));
5734                 version = SPOOLSS_DRIVER_VERSION_200X;
5735         }
5736
5737         result = construct_printer_driver_info_level(p->mem_ctx,
5738                                                      get_session_info_system(),
5739                                                      p->msg_ctx,
5740                                                      r->in.level, r->out.info,
5741                                                      snum, printer->servername,
5742                                                      r->in.architecture,
5743                                                      version);
5744         if (!W_ERROR_IS_OK(result)) {
5745                 goto err_info_free;
5746         }
5747
5748         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5749                                                r->out.info, r->in.level);
5750         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5751
5752         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5753
5754 err_info_free:
5755         TALLOC_FREE(r->out.info);
5756         return result;
5757 }
5758
5759
5760 /****************************************************************
5761  _spoolss_StartPagePrinter
5762 ****************************************************************/
5763
5764 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5765                                  struct spoolss_StartPagePrinter *r)
5766 {
5767         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5768
5769         if (!Printer) {
5770                 DEBUG(3,("_spoolss_StartPagePrinter: "
5771                         "Error in startpageprinter printer handle\n"));
5772                 return WERR_BADFID;
5773         }
5774
5775         Printer->page_started = true;
5776         return WERR_OK;
5777 }
5778
5779 /****************************************************************
5780  _spoolss_EndPagePrinter
5781 ****************************************************************/
5782
5783 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5784                                struct spoolss_EndPagePrinter *r)
5785 {
5786         int snum;
5787
5788         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5789
5790         if (!Printer) {
5791                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5792                         OUR_HANDLE(r->in.handle)));
5793                 return WERR_BADFID;
5794         }
5795
5796         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5797                 return WERR_BADFID;
5798
5799         Printer->page_started = false;
5800         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5801
5802         return WERR_OK;
5803 }
5804
5805 /****************************************************************
5806  _spoolss_StartDocPrinter
5807 ****************************************************************/
5808
5809 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5810                                 struct spoolss_StartDocPrinter *r)
5811 {
5812         struct spoolss_DocumentInfo1 *info_1;
5813         int snum;
5814         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5815         WERROR werr;
5816         char *rhost;
5817         int rc;
5818
5819         if (!Printer) {
5820                 DEBUG(2,("_spoolss_StartDocPrinter: "
5821                         "Invalid handle (%s:%u:%u)\n",
5822                         OUR_HANDLE(r->in.handle)));
5823                 return WERR_BADFID;
5824         }
5825
5826         if (Printer->jobid) {
5827                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5828                           "StartDocPrinter called twice! "
5829                           "(existing jobid = %d)\n", Printer->jobid));
5830                 return WERR_INVALID_HANDLE;
5831         }
5832
5833         if (r->in.info_ctr->level != 1) {
5834                 return WERR_UNKNOWN_LEVEL;
5835         }
5836
5837         info_1 = r->in.info_ctr->info.info1;
5838
5839         /*
5840          * a nice thing with NT is it doesn't listen to what you tell it.
5841          * when asked to send _only_ RAW datas, it tries to send datas
5842          * in EMF format.
5843          *
5844          * So I add checks like in NT Server ...
5845          */
5846
5847         if (info_1->datatype) {
5848                 /*
5849                  * The v4 driver model used in Windows 8 declares print jobs
5850                  * intended to bypass the XPS processing layer by setting
5851                  * datatype to "XPS_PASS" instead of "RAW".
5852                  */
5853                 if ((strcmp(info_1->datatype, "RAW") != 0)
5854                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5855                         *r->out.job_id = 0;
5856                         return WERR_INVALID_DATATYPE;
5857                 }
5858         }
5859
5860         /* get the share number of the printer */
5861         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5862                 return WERR_BADFID;
5863         }
5864
5865         rc = get_remote_hostname(p->remote_address,
5866                                  &rhost,
5867                                  p->mem_ctx);
5868         if (rc < 0) {
5869                 return WERR_NOMEM;
5870         }
5871         if (strequal(rhost,"UNKNOWN")) {
5872                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5873                                                          p->mem_ctx);
5874                 if (rhost == NULL) {
5875                         return WERR_NOMEM;
5876                 }
5877         }
5878
5879         werr = print_job_start(p->session_info,
5880                                p->msg_ctx,
5881                                rhost,
5882                                snum,
5883                                info_1->document_name,
5884                                info_1->output_file,
5885                                Printer->devmode,
5886                                &Printer->jobid);
5887
5888         /* An error occured in print_job_start() so return an appropriate
5889            NT error code. */
5890
5891         if (!W_ERROR_IS_OK(werr)) {
5892                 return werr;
5893         }
5894
5895         Printer->document_started = true;
5896         *r->out.job_id = Printer->jobid;
5897
5898         return WERR_OK;
5899 }
5900
5901 /****************************************************************
5902  _spoolss_EndDocPrinter
5903 ****************************************************************/
5904
5905 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5906                               struct spoolss_EndDocPrinter *r)
5907 {
5908         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5909         NTSTATUS status;
5910         int snum;
5911
5912         if (!Printer) {
5913                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5914                         OUR_HANDLE(r->in.handle)));
5915                 return WERR_BADFID;
5916         }
5917
5918         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5919                 return WERR_BADFID;
5920         }
5921
5922         Printer->document_started = false;
5923         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5924         if (!NT_STATUS_IS_OK(status)) {
5925                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5926                           "print_job_end failed [%s]\n",
5927                           nt_errstr(status)));
5928         }
5929
5930         Printer->jobid = 0;
5931         return ntstatus_to_werror(status);
5932 }
5933
5934 /****************************************************************
5935  _spoolss_WritePrinter
5936 ****************************************************************/
5937
5938 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5939                              struct spoolss_WritePrinter *r)
5940 {
5941         ssize_t buffer_written;
5942         int snum;
5943         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5944
5945         if (!Printer) {
5946                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5947                         OUR_HANDLE(r->in.handle)));
5948                 *r->out.num_written = r->in._data_size;
5949                 return WERR_BADFID;
5950         }
5951
5952         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5953                 return WERR_BADFID;
5954
5955         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5956         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5957                                                    snum, Printer->jobid,
5958                                                    (const char *)r->in.data.data,
5959                                                    (size_t)r->in._data_size);
5960         if (buffer_written == (ssize_t)-1) {
5961                 *r->out.num_written = 0;
5962                 if (errno == ENOSPC)
5963                         return WERR_NO_SPOOL_SPACE;
5964                 else
5965                         return WERR_ACCESS_DENIED;
5966         }
5967
5968         *r->out.num_written = r->in._data_size;
5969
5970         return WERR_OK;
5971 }
5972
5973 /********************************************************************
5974  * api_spoolss_getprinter
5975  * called from the spoolss dispatcher
5976  *
5977  ********************************************************************/
5978
5979 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5980                               struct pipes_struct *p)
5981 {
5982         const struct auth_session_info *session_info = p->session_info;
5983         int snum;
5984         WERROR errcode = WERR_BADFUNC;
5985         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5986
5987         if (!Printer) {
5988                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5989                         OUR_HANDLE(handle)));
5990                 return WERR_BADFID;
5991         }
5992
5993         if (!get_printer_snum(p, handle, &snum, NULL))
5994                 return WERR_BADFID;
5995
5996         switch (command) {
5997         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5998                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5999                 break;
6000         case SPOOLSS_PRINTER_CONTROL_RESUME:
6001         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6002                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6003                 break;
6004         case SPOOLSS_PRINTER_CONTROL_PURGE:
6005                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6006                 break;
6007         default:
6008                 return WERR_UNKNOWN_LEVEL;
6009         }
6010
6011         return errcode;
6012 }
6013
6014
6015 /****************************************************************
6016  _spoolss_AbortPrinter
6017  * From MSDN: "Deletes printer's spool file if printer is configured
6018  * for spooling"
6019 ****************************************************************/
6020
6021 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6022                              struct spoolss_AbortPrinter *r)
6023 {
6024         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
6025         int             snum;
6026         WERROR          errcode = WERR_OK;
6027
6028         if (!Printer) {
6029                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6030                         OUR_HANDLE(r->in.handle)));
6031                 return WERR_BADFID;
6032         }
6033
6034         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6035                 return WERR_BADFID;
6036
6037         if (!Printer->document_started) {
6038                 return WERR_SPL_NO_STARTDOC;
6039         }
6040
6041         errcode = print_job_delete(p->session_info,
6042                                    p->msg_ctx,
6043                                    snum,
6044                                    Printer->jobid);
6045
6046         return errcode;
6047 }
6048
6049 /********************************************************************
6050  * called by spoolss_api_setprinter
6051  * when updating a printer description
6052  ********************************************************************/
6053
6054 static WERROR update_printer_sec(struct policy_handle *handle,
6055                                  struct pipes_struct *p,
6056                                  struct sec_desc_buf *secdesc_ctr)
6057 {
6058         struct spoolss_security_descriptor *new_secdesc = NULL;
6059         struct spoolss_security_descriptor *old_secdesc = NULL;
6060         const char *printer;
6061         WERROR result;
6062         int snum;
6063         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6064         struct dcerpc_binding_handle *b;
6065         TALLOC_CTX *tmp_ctx = NULL;
6066
6067         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6068                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6069                          OUR_HANDLE(handle)));
6070
6071                 result = WERR_BADFID;
6072                 goto done;
6073         }
6074
6075         if (secdesc_ctr == NULL) {
6076                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6077                 result = WERR_INVALID_PARAM;
6078                 goto done;
6079         }
6080         printer = lp_const_servicename(snum);
6081
6082         /* Check the user has permissions to change the security
6083            descriptor.  By experimentation with two NT machines, the user
6084            requires Full Access to the printer to change security
6085            information. */
6086
6087         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6088                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6089                 result = WERR_ACCESS_DENIED;
6090                 goto done;
6091         }
6092
6093         tmp_ctx = talloc_new(p->mem_ctx);
6094         if (!tmp_ctx) {
6095                 return WERR_NOMEM;
6096         }
6097
6098         result = winreg_printer_binding_handle(tmp_ctx,
6099                                                get_session_info_system(),
6100                                                p->msg_ctx,
6101                                                &b);
6102         if (!W_ERROR_IS_OK(result)) {
6103                 goto done;
6104         }
6105
6106         /* NT seems to like setting the security descriptor even though
6107            nothing may have actually changed. */
6108         result = winreg_get_printer_secdesc(tmp_ctx, b,
6109                                             printer,
6110                                             &old_secdesc);
6111         if (!W_ERROR_IS_OK(result)) {
6112                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6113                 result = WERR_BADFID;
6114                 goto done;
6115         }
6116
6117         if (DEBUGLEVEL >= 10) {
6118                 struct security_acl *the_acl;
6119                 int i;
6120
6121                 the_acl = old_secdesc->dacl;
6122                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6123                            printer, the_acl->num_aces));
6124
6125                 for (i = 0; i < the_acl->num_aces; i++) {
6126                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6127                                            &the_acl->aces[i].trustee),
6128                                   the_acl->aces[i].access_mask));
6129                 }
6130
6131                 the_acl = secdesc_ctr->sd->dacl;
6132
6133                 if (the_acl) {
6134                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6135                                    printer, the_acl->num_aces));
6136
6137                         for (i = 0; i < the_acl->num_aces; i++) {
6138                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6139                                                    &the_acl->aces[i].trustee),
6140                                            the_acl->aces[i].access_mask));
6141                         }
6142                 } else {
6143                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6144                 }
6145         }
6146
6147         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6148         if (new_secdesc == NULL) {
6149                 result = WERR_NOMEM;
6150                 goto done;
6151         }
6152
6153         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6154                 result = WERR_OK;
6155                 goto done;
6156         }
6157
6158         result = winreg_set_printer_secdesc(tmp_ctx, b,
6159                                             printer,
6160                                             new_secdesc);
6161
6162 done:
6163         talloc_free(tmp_ctx);
6164         return result;
6165 }
6166
6167 /********************************************************************
6168  Canonicalize printer info from a client
6169  ********************************************************************/
6170
6171 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6172                              struct spoolss_SetPrinterInfo2 *info2,
6173                              int snum)
6174 {
6175         fstring printername;
6176         const char *p;
6177
6178         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6179                 "portname=%s drivername=%s comment=%s location=%s\n",
6180                 info2->servername, info2->printername, info2->sharename,
6181                 info2->portname, info2->drivername, info2->comment,
6182                 info2->location));
6183
6184         /* we force some elements to "correct" values */
6185         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6186         if (info2->servername == NULL) {
6187                 return false;
6188         }
6189         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6190         if (info2->sharename == NULL) {
6191                 return false;
6192         }
6193
6194         /* check to see if we allow printername != sharename */
6195         if (lp_force_printername(snum)) {
6196                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6197                                         lp_netbios_name(), info2->sharename);
6198         } else {
6199                 /* make sure printername is in \\server\printername format */
6200                 fstrcpy(printername, info2->printername);
6201                 p = printername;
6202                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6203                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6204                                 p++;
6205                 }
6206
6207                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6208                                         lp_netbios_name(), p);
6209         }
6210         if (info2->printername == NULL) {
6211                 return false;
6212         }
6213
6214         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6215         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6216
6217         return true;
6218 }
6219
6220 /****************************************************************************
6221 ****************************************************************************/
6222
6223 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6224 {
6225         char *cmd = lp_addport_command(talloc_tos());
6226         char *command = NULL;
6227         int ret;
6228         bool is_print_op = false;
6229
6230         if ( !*cmd ) {
6231                 return WERR_ACCESS_DENIED;
6232         }
6233
6234         command = talloc_asprintf(ctx,
6235                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6236         if (!command) {
6237                 return WERR_NOMEM;
6238         }
6239
6240         if ( token )
6241                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6242
6243         DEBUG(10,("Running [%s]\n", command));
6244
6245         /********* BEGIN SePrintOperatorPrivilege **********/
6246
6247         if ( is_print_op )
6248                 become_root();
6249
6250         ret = smbrun(command, NULL);
6251
6252         if ( is_print_op )
6253                 unbecome_root();
6254
6255         /********* END SePrintOperatorPrivilege **********/
6256
6257         DEBUGADD(10,("returned [%d]\n", ret));
6258
6259         TALLOC_FREE(command);
6260
6261         if ( ret != 0 ) {
6262                 return WERR_ACCESS_DENIED;
6263         }
6264
6265         return WERR_OK;
6266 }
6267
6268 /****************************************************************************
6269 ****************************************************************************/
6270
6271 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6272                                    int snum)
6273 {
6274         /*
6275          * As we do not know if we are embedded in the file server process
6276          * or not, we have to pretend that all shares are in use.
6277          */
6278         return true;
6279 }
6280
6281 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6282                              struct spoolss_SetPrinterInfo2 *info2,
6283                              const char *remote_machine,
6284                              struct messaging_context *msg_ctx)
6285 {
6286         char *cmd = lp_addprinter_command(talloc_tos());
6287         char **qlines;
6288         char *command = NULL;
6289         int numlines;
6290         int ret;
6291         int fd;
6292         bool is_print_op = false;
6293
6294         if (!remote_machine) {
6295                 return false;
6296         }
6297
6298         command = talloc_asprintf(ctx,
6299                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6300                         cmd, info2->printername, info2->sharename,
6301                         info2->portname, info2->drivername,
6302                         info2->location, info2->comment, remote_machine);
6303         if (!command) {
6304                 return false;
6305         }
6306
6307         if ( token )
6308                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6309
6310         DEBUG(10,("Running [%s]\n", command));
6311
6312         /********* BEGIN SePrintOperatorPrivilege **********/
6313
6314         if ( is_print_op )
6315                 become_root();
6316
6317         if ( (ret = smbrun(command, &fd)) == 0 ) {
6318                 /* Tell everyone we updated smb.conf. */
6319                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6320         }
6321
6322         if ( is_print_op )
6323                 unbecome_root();
6324
6325         /********* END SePrintOperatorPrivilege **********/
6326
6327         DEBUGADD(10,("returned [%d]\n", ret));
6328
6329         TALLOC_FREE(command);
6330
6331         if ( ret != 0 ) {
6332                 if (fd != -1)
6333                         close(fd);
6334                 return false;
6335         }
6336
6337         /* reload our services immediately */
6338         become_root();
6339         reload_services(NULL, spoolss_conn_snum_used, false);
6340         unbecome_root();
6341
6342         numlines = 0;
6343         /* Get lines and convert them back to dos-codepage */
6344         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6345         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6346         close(fd);
6347
6348         /* Set the portname to what the script says the portname should be. */
6349         /* but don't require anything to be return from the script exit a good error code */
6350
6351         if (numlines) {
6352                 /* Set the portname to what the script says the portname should be. */
6353                 info2->portname = talloc_strdup(ctx, qlines[0]);
6354                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6355         }
6356
6357         TALLOC_FREE(qlines);
6358         return true;
6359 }
6360
6361 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6362                                const struct auth_session_info *session_info,
6363                                struct messaging_context *msg_ctx,
6364                                int snum,
6365                                struct spoolss_SetPrinterInfo2 *printer,
6366                                struct spoolss_PrinterInfo2 *old_printer)
6367 {
6368         bool force_update = (old_printer == NULL);
6369         const char *dnsdomname;
6370         const char *longname;
6371         const char *uncname;
6372         const char *spooling;
6373         DATA_BLOB buffer;
6374         WERROR result = WERR_OK;
6375         struct dcerpc_binding_handle *b;
6376         TALLOC_CTX *tmp_ctx;
6377         bool ok;
6378
6379         tmp_ctx = talloc_new(mem_ctx);
6380         if (!tmp_ctx) {
6381                 return WERR_NOMEM;
6382         }
6383
6384         result = winreg_printer_binding_handle(tmp_ctx,
6385                                                session_info,
6386                                                msg_ctx,
6387                                                &b);
6388         if (!W_ERROR_IS_OK(result)) {
6389                 goto done;
6390         }
6391
6392         if (printer->drivername != NULL &&
6393             (force_update ||
6394              !strequal(printer->drivername, old_printer->drivername))) {
6395                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6396                 if (!ok) {
6397                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6398                         result = WERR_INVALID_DATA;
6399                         goto done;
6400                 }
6401                 result = winreg_set_printer_dataex(tmp_ctx, b,
6402                                           printer->sharename,
6403                                           SPOOL_DSSPOOLER_KEY,
6404                                           SPOOL_REG_DRIVERNAME,
6405                                           REG_SZ,
6406                                           buffer.data,
6407                                           buffer.length);
6408                 if (!W_ERROR_IS_OK(result)) {
6409                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6410                         goto done;
6411                 }
6412
6413                 if (!force_update) {
6414                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6415                                 printer->drivername));
6416
6417                         notify_printer_driver(server_event_context(), msg_ctx,
6418                                               snum, printer->drivername ?
6419                                               printer->drivername : "");
6420                 }
6421         }
6422
6423         if (printer->comment != NULL &&
6424             (force_update ||
6425              !strequal(printer->comment, old_printer->comment))) {
6426                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6427                 if (!ok) {
6428                         DEBUG(0, ("comment data corrupted\n"));
6429                         result = WERR_INVALID_DATA;
6430                         goto done;
6431                 }
6432                 result = winreg_set_printer_dataex(tmp_ctx, b,
6433                                           printer->sharename,
6434                                           SPOOL_DSSPOOLER_KEY,
6435                                           SPOOL_REG_DESCRIPTION,
6436                                           REG_SZ,
6437                                           buffer.data,
6438                                           buffer.length);
6439                 if (!W_ERROR_IS_OK(result)) {
6440                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6441                         goto done;
6442                 }
6443
6444                 if (!force_update) {
6445                         notify_printer_comment(server_event_context(), msg_ctx,
6446                                                snum, printer->comment ?
6447                                                printer->comment : "");
6448                 }
6449         }
6450
6451         if (printer->sharename != NULL &&
6452             (force_update ||
6453              !strequal(printer->sharename, old_printer->sharename))) {
6454                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6455                 if (!ok) {
6456                         DEBUG(0, ("sharename 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_PRINTSHARENAME,
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_sharename(server_event_context(),
6474                                                  msg_ctx,
6475                                                  snum, printer->sharename ?
6476                                                  printer->sharename : "");
6477                 }
6478
6479                 /* name change, purge any cache entries for the old */
6480                 prune_printername_cache();
6481         }
6482
6483         if (printer->printername != NULL &&
6484             (force_update ||
6485              !strequal(printer->printername, old_printer->printername))) {
6486                 const char *p;
6487
6488                 p = strrchr(printer->printername, '\\' );
6489                 if (p != NULL) {
6490                         p++;
6491                 } else {
6492                         p = printer->printername;
6493                 }
6494
6495                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6496                 if (!ok) {
6497                         DEBUG(0, ("printername data corrupted\n"));
6498                         result = WERR_INVALID_DATA;
6499                         goto done;
6500                 }
6501                 result = winreg_set_printer_dataex(tmp_ctx, b,
6502                                           printer->sharename,
6503                                           SPOOL_DSSPOOLER_KEY,
6504                                           SPOOL_REG_PRINTERNAME,
6505                                           REG_SZ,
6506                                           buffer.data,
6507                                           buffer.length);
6508                 if (!W_ERROR_IS_OK(result)) {
6509                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6510                         goto done;
6511                 }
6512
6513                 if (!force_update) {
6514                         notify_printer_printername(server_event_context(),
6515                                                    msg_ctx, snum, p ? p : "");
6516                 }
6517
6518                 /* name change, purge any cache entries for the old */
6519                 prune_printername_cache();
6520         }
6521
6522         if (printer->portname != NULL &&
6523             (force_update ||
6524              !strequal(printer->portname, old_printer->portname))) {
6525                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6526                 if (!ok) {
6527                         DEBUG(0, ("portname data corrupted\n"));
6528                         result = WERR_INVALID_DATA;
6529                         goto done;
6530                 }
6531                 result = winreg_set_printer_dataex(tmp_ctx, b,
6532                                           printer->sharename,
6533                                           SPOOL_DSSPOOLER_KEY,
6534                                           SPOOL_REG_PORTNAME,
6535                                           REG_SZ,
6536                                           buffer.data,
6537                                           buffer.length);
6538                 if (!W_ERROR_IS_OK(result)) {
6539                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6540                         goto done;
6541                 }
6542
6543                 if (!force_update) {
6544                         notify_printer_port(server_event_context(),
6545                                             msg_ctx, snum, printer->portname ?
6546                                             printer->portname : "");
6547                 }
6548         }
6549
6550         if (printer->location != NULL &&
6551             (force_update ||
6552              !strequal(printer->location, old_printer->location))) {
6553                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6554                 if (!ok) {
6555                         DEBUG(0, ("location data corrupted\n"));
6556                         result = WERR_INVALID_DATA;
6557                         goto done;
6558                 }
6559                 result = winreg_set_printer_dataex(tmp_ctx, b,
6560                                           printer->sharename,
6561                                           SPOOL_DSSPOOLER_KEY,
6562                                           SPOOL_REG_LOCATION,
6563                                           REG_SZ,
6564                                           buffer.data,
6565                                           buffer.length);
6566                 if (!W_ERROR_IS_OK(result)) {
6567                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6568                         goto done;
6569                 }
6570
6571                 if (!force_update) {
6572                         notify_printer_location(server_event_context(),
6573                                                 msg_ctx, snum,
6574                                                 printer->location ?
6575                                                 printer->location : "");
6576                 }
6577         }
6578
6579         if (printer->sepfile != NULL &&
6580             (force_update ||
6581              !strequal(printer->sepfile, old_printer->sepfile))) {
6582                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6583                 if (!ok) {
6584                         DEBUG(0, ("sepfile data corrupted\n"));
6585                         result = WERR_INVALID_DATA;
6586                         goto done;
6587                 }
6588                 result = winreg_set_printer_dataex(tmp_ctx, b,
6589                                           printer->sharename,
6590                                           SPOOL_DSSPOOLER_KEY,
6591                                           SPOOL_REG_PRINTSEPARATORFILE,
6592                                           REG_SZ,
6593                                           buffer.data,
6594                                           buffer.length);
6595                 if (!W_ERROR_IS_OK(result)) {
6596                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6597                         goto done;
6598                 }
6599
6600                 if (!force_update) {
6601                         notify_printer_sepfile(server_event_context(),
6602                                                msg_ctx, snum,
6603                                                printer->sepfile ?
6604                                                printer->sepfile : "");
6605                 }
6606         }
6607
6608         if (printer->starttime != 0 &&
6609             (force_update ||
6610              printer->starttime != old_printer->starttime)) {
6611                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6612                 SIVAL(buffer.data, 0, printer->starttime);
6613                 result = winreg_set_printer_dataex(tmp_ctx, b,
6614                                           printer->sharename,
6615                                           SPOOL_DSSPOOLER_KEY,
6616                                           SPOOL_REG_PRINTSTARTTIME,
6617                                           REG_DWORD,
6618                                           buffer.data,
6619                                           buffer.length);
6620                 if (!W_ERROR_IS_OK(result)) {
6621                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6622                         goto done;
6623                 }
6624         }
6625
6626         if (printer->untiltime != 0 &&
6627             (force_update ||
6628              printer->untiltime != old_printer->untiltime)) {
6629                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6630                 SIVAL(buffer.data, 0, printer->untiltime);
6631                 result = winreg_set_printer_dataex(tmp_ctx, b,
6632                                           printer->sharename,
6633                                           SPOOL_DSSPOOLER_KEY,
6634                                           SPOOL_REG_PRINTENDTIME,
6635                                           REG_DWORD,
6636                                           buffer.data,
6637                                           buffer.length);
6638                 if (!W_ERROR_IS_OK(result)) {
6639                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6640                         goto done;
6641                 }
6642         }
6643
6644         if (force_update || printer->priority != old_printer->priority) {
6645                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6646                 SIVAL(buffer.data, 0, printer->priority);
6647                 result = winreg_set_printer_dataex(tmp_ctx, b,
6648                                           printer->sharename,
6649                                           SPOOL_DSSPOOLER_KEY,
6650                                           SPOOL_REG_PRIORITY,
6651                                           REG_DWORD,
6652                                           buffer.data,
6653                                           buffer.length);
6654                 if (!W_ERROR_IS_OK(result)) {
6655                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6656                         goto done;
6657                 }
6658         }
6659
6660         if (force_update || printer->attributes != old_printer->attributes) {
6661                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6662                 SIVAL(buffer.data, 0, (printer->attributes &
6663                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6664                 result = winreg_set_printer_dataex(tmp_ctx, b,
6665                                           printer->sharename,
6666                                           SPOOL_DSSPOOLER_KEY,
6667                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6668                                           REG_DWORD,
6669                                           buffer.data,
6670                                           buffer.length);
6671                 if (!W_ERROR_IS_OK(result)) {
6672                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6673                         goto done;
6674                 }
6675
6676                 switch (printer->attributes & 0x3) {
6677                         case 0:
6678                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6679                                 break;
6680                         case 1:
6681                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6682                                 break;
6683                         case 2:
6684                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6685                                 break;
6686                         default:
6687                                 spooling = "unknown";
6688                 }
6689                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6690                 if (!ok) {
6691                         DEBUG(0, ("printSpooling data corrupted\n"));
6692                         result = WERR_INVALID_DATA;
6693                         goto done;
6694                 }
6695                 winreg_set_printer_dataex(tmp_ctx, b,
6696                                           printer->sharename,
6697                                           SPOOL_DSSPOOLER_KEY,
6698                                           SPOOL_REG_PRINTSPOOLING,
6699                                           REG_SZ,
6700                                           buffer.data,
6701                                           buffer.length);
6702         }
6703
6704         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6705         if (!ok) {
6706                 DEBUG(0, ("shortServerName data corrupted\n"));
6707                 result = WERR_INVALID_DATA;
6708                 goto done;
6709         }
6710         result = winreg_set_printer_dataex(tmp_ctx, b,
6711                                   printer->sharename,
6712                                   SPOOL_DSSPOOLER_KEY,
6713                                   SPOOL_REG_SHORTSERVERNAME,
6714                                   REG_SZ,
6715                                   buffer.data,
6716                                   buffer.length);
6717         if (!W_ERROR_IS_OK(result)) {
6718                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6719                 goto done;
6720         }
6721
6722         dnsdomname = get_mydnsfullname();
6723         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6724                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6725         } else {
6726                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6727         }
6728         if (longname == NULL) {
6729                 result = WERR_NOMEM;
6730                 goto done;
6731         }
6732
6733         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6734         if (!ok) {
6735                 DEBUG(0, ("longname data corrupted\n"));
6736                 result = WERR_INVALID_DATA;
6737                 goto done;
6738         }
6739         result = winreg_set_printer_dataex(tmp_ctx, b,
6740                                            printer->sharename,
6741                                            SPOOL_DSSPOOLER_KEY,
6742                                            SPOOL_REG_SERVERNAME,
6743                                            REG_SZ,
6744                                            buffer.data,
6745                                            buffer.length);
6746         if (!W_ERROR_IS_OK(result)) {
6747                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6748                 goto done;
6749         }
6750
6751         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6752                                   lp_netbios_name(), printer->sharename);
6753         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6754         if (!ok) {
6755                 DEBUG(0, ("uncName data corrupted\n"));
6756                 result = WERR_INVALID_DATA;
6757                 goto done;
6758         }
6759         result = winreg_set_printer_dataex(tmp_ctx, b,
6760                                   printer->sharename,
6761                                   SPOOL_DSSPOOLER_KEY,
6762                                   SPOOL_REG_UNCNAME,
6763                                   REG_SZ,
6764                                   buffer.data,
6765                                   buffer.length);
6766         if (!W_ERROR_IS_OK(result)) {
6767                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6768                 goto done;
6769         }
6770
6771 done:
6772         talloc_free(tmp_ctx);
6773         return result;
6774 }
6775
6776 /********************************************************************
6777  * Called by spoolss_api_setprinter
6778  * when updating a printer description.
6779  ********************************************************************/
6780
6781 static WERROR update_printer(struct pipes_struct *p,
6782                              struct policy_handle *handle,
6783                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6784                              struct spoolss_DeviceMode *devmode)
6785 {
6786         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6787         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6788         struct spoolss_PrinterInfo2 *old_printer;
6789         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6790         int snum;
6791         WERROR result = WERR_OK;
6792         TALLOC_CTX *tmp_ctx;
6793         struct dcerpc_binding_handle *b;
6794
6795         DEBUG(8,("update_printer\n"));
6796
6797         tmp_ctx = talloc_new(p->mem_ctx);
6798         if (tmp_ctx == NULL) {
6799                 return WERR_NOMEM;
6800         }
6801
6802         if (!Printer) {
6803                 result = WERR_BADFID;
6804                 goto done;
6805         }
6806
6807         if (!get_printer_snum(p, handle, &snum, NULL)) {
6808                 result = WERR_BADFID;
6809                 goto done;
6810         }
6811
6812         result = winreg_printer_binding_handle(tmp_ctx,
6813                                                get_session_info_system(),
6814                                                p->msg_ctx,
6815                                                &b);
6816         if (!W_ERROR_IS_OK(result)) {
6817                 goto done;
6818         }
6819
6820         result = winreg_get_printer(tmp_ctx, b,
6821                                     lp_const_servicename(snum),
6822                                     &old_printer);
6823         if (!W_ERROR_IS_OK(result)) {
6824                 result = WERR_BADFID;
6825                 goto done;
6826         }
6827
6828         /* Do sanity check on the requested changes for Samba */
6829         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6830                 result = WERR_INVALID_PARAM;
6831                 goto done;
6832         }
6833
6834         /* FIXME!!! If the driver has changed we really should verify that
6835            it is installed before doing much else   --jerry */
6836
6837         /* Check calling user has permission to update printer description */
6838         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6839                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6840                 result = WERR_ACCESS_DENIED;
6841                 goto done;
6842         }
6843
6844         /* Call addprinter hook */
6845         /* Check changes to see if this is really needed */
6846
6847         if (*lp_addprinter_command(talloc_tos()) &&
6848                         (!strequal(printer->drivername, old_printer->drivername) ||
6849                          !strequal(printer->comment, old_printer->comment) ||
6850                          !strequal(printer->portname, old_printer->portname) ||
6851                          !strequal(printer->location, old_printer->location)) )
6852         {
6853                 char *raddr;
6854
6855                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6856                                                          p->mem_ctx);
6857                 if (raddr == NULL) {
6858                         return WERR_NOMEM;
6859                 }
6860
6861                 /* add_printer_hook() will call reload_services() */
6862                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6863                                       printer, raddr,
6864                                       p->msg_ctx)) {
6865                         result = WERR_ACCESS_DENIED;
6866                         goto done;
6867                 }
6868         }
6869
6870         result = update_dsspooler(tmp_ctx,
6871                                   get_session_info_system(),
6872                                   p->msg_ctx,
6873                                   snum,
6874                                   printer,
6875                                   old_printer);
6876         if (!W_ERROR_IS_OK(result)) {
6877                 goto done;
6878         }
6879
6880         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6881
6882         if (devmode == NULL) {
6883                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6884         }
6885         result = winreg_update_printer(tmp_ctx, b,
6886                                        printer->sharename,
6887                                        printer_mask,
6888                                        printer,
6889                                        devmode,
6890                                        NULL);
6891
6892 done:
6893         talloc_free(tmp_ctx);
6894
6895         return result;
6896 }
6897
6898 /****************************************************************************
6899 ****************************************************************************/
6900 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6901                                            struct policy_handle *handle,
6902                                            struct spoolss_SetPrinterInfo7 *info7)
6903 {
6904 #ifdef HAVE_ADS
6905         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6906         WERROR result;
6907         int snum;
6908         struct printer_handle *Printer;
6909
6910         if ( lp_security() != SEC_ADS ) {
6911                 return WERR_UNKNOWN_LEVEL;
6912         }
6913
6914         Printer = find_printer_index_by_hnd(p, handle);
6915
6916         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6917
6918         if (!Printer)
6919                 return WERR_BADFID;
6920
6921         if (!get_printer_snum(p, handle, &snum, NULL))
6922                 return WERR_BADFID;
6923
6924         result = winreg_get_printer_internal(p->mem_ctx,
6925                                     get_session_info_system(),
6926                                     p->msg_ctx,
6927                                     lp_servicename(talloc_tos(), snum),
6928                                     &pinfo2);
6929         if (!W_ERROR_IS_OK(result)) {
6930                 return WERR_BADFID;
6931         }
6932
6933         nt_printer_publish(pinfo2,
6934                            get_session_info_system(),
6935                            p->msg_ctx,
6936                            pinfo2,
6937                            info7->action);
6938
6939         TALLOC_FREE(pinfo2);
6940         return WERR_OK;
6941 #else
6942         return WERR_UNKNOWN_LEVEL;
6943 #endif
6944 }
6945
6946 /********************************************************************
6947  ********************************************************************/
6948
6949 static WERROR update_printer_devmode(struct pipes_struct *p,
6950                                      struct policy_handle *handle,
6951                                      struct spoolss_DeviceMode *devmode)
6952 {
6953         int snum;
6954         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6955         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6956
6957         DEBUG(8,("update_printer_devmode\n"));
6958
6959         if (!Printer) {
6960                 return WERR_BADFID;
6961         }
6962
6963         if (!get_printer_snum(p, handle, &snum, NULL)) {
6964                 return WERR_BADFID;
6965         }
6966
6967         /* Check calling user has permission to update printer description */
6968         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6969                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6970                 return WERR_ACCESS_DENIED;
6971         }
6972
6973         return winreg_update_printer_internal(p->mem_ctx,
6974                                      get_session_info_system(),
6975                                      p->msg_ctx,
6976                                      lp_const_servicename(snum),
6977                                      info2_mask,
6978                                      NULL,
6979                                      devmode,
6980                                      NULL);
6981 }
6982
6983
6984 /****************************************************************
6985  _spoolss_SetPrinter
6986 ****************************************************************/
6987
6988 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6989                            struct spoolss_SetPrinter *r)
6990 {
6991         WERROR result;
6992
6993         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6994
6995         if (!Printer) {
6996                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6997                         OUR_HANDLE(r->in.handle)));
6998                 return WERR_BADFID;
6999         }
7000
7001         /* check the level */
7002         switch (r->in.info_ctr->level) {
7003                 case 0:
7004                         return control_printer(r->in.handle, r->in.command, p);
7005                 case 2:
7006                         result = update_printer(p, r->in.handle,
7007                                                 r->in.info_ctr,
7008                                                 r->in.devmode_ctr->devmode);
7009                         if (!W_ERROR_IS_OK(result))
7010                                 return result;
7011                         if (r->in.secdesc_ctr->sd)
7012                                 result = update_printer_sec(r->in.handle, p,
7013                                                             r->in.secdesc_ctr);
7014                         return result;
7015                 case 3:
7016                         return update_printer_sec(r->in.handle, p,
7017                                                   r->in.secdesc_ctr);
7018                 case 4: {
7019                         struct spoolss_PrinterInfo2 *old_printer;
7020                         struct spoolss_SetPrinterInfo2 *set_old_printer;
7021                         struct spoolss_SetPrinterInfoCtr *info_ctr;
7022                         struct dcerpc_binding_handle *b;
7023                         int snum;
7024                         TALLOC_CTX *tmp_ctx;
7025
7026                         tmp_ctx = talloc_new(p->mem_ctx);
7027                         if (tmp_ctx == NULL) {
7028                                 return WERR_NOMEM;
7029                         }
7030
7031                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7032                                 TALLOC_FREE(tmp_ctx);
7033                                 return WERR_BADFID;
7034                         }
7035
7036                         result = winreg_printer_binding_handle(tmp_ctx,
7037                                                                get_session_info_system(),
7038                                                                p->msg_ctx,
7039                                                                &b);
7040                         if (!W_ERROR_IS_OK(result)) {
7041                                 TALLOC_FREE(tmp_ctx);
7042                                 return result;
7043                         }
7044
7045                         result = winreg_get_printer(tmp_ctx, b,
7046                                                     lp_const_servicename(snum),
7047                                                     &old_printer);
7048                         if (!W_ERROR_IS_OK(result)) {
7049                                 TALLOC_FREE(tmp_ctx);
7050                                 return WERR_BADFID;
7051                         }
7052
7053                         old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7054                         if (old_printer->servername == NULL) {
7055                                 TALLOC_FREE(tmp_ctx);
7056                                 return WERR_NOMEM;
7057                         }
7058
7059                         old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7060                         if (old_printer->printername == NULL) {
7061                                 TALLOC_FREE(tmp_ctx);
7062                                 return WERR_NOMEM;
7063                         }
7064
7065                         old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7066
7067                         set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7068                         if (set_old_printer == NULL) {
7069                                 TALLOC_FREE(tmp_ctx);
7070                                 return WERR_NOMEM;
7071                         }
7072
7073                         spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7074
7075                         info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7076                         if (info_ctr == NULL) {
7077                                 TALLOC_FREE(tmp_ctx);
7078                                 return WERR_NOMEM;
7079                         }
7080
7081                         info_ctr->level = 2;
7082                         info_ctr->info.info2 = set_old_printer;
7083
7084                         result = update_printer(p, r->in.handle,
7085                                                 info_ctr,
7086                                                 r->in.devmode_ctr->devmode);
7087
7088                         if (!W_ERROR_IS_OK(result)) {
7089                                 TALLOC_FREE(tmp_ctx);
7090                                 return result;
7091                         }
7092
7093                         if (r->in.secdesc_ctr->sd) {
7094                                 result = update_printer_sec(r->in.handle, p,
7095                                                             r->in.secdesc_ctr);
7096                         }
7097
7098                         TALLOC_FREE(tmp_ctx);
7099                         return result;
7100                 }
7101                 case 7:
7102                         return publish_or_unpublish_printer(p, r->in.handle,
7103                                                             r->in.info_ctr->info.info7);
7104                 case 8:
7105                         return update_printer_devmode(p, r->in.handle,
7106                                                       r->in.devmode_ctr->devmode);
7107                 default:
7108                         return WERR_UNKNOWN_LEVEL;
7109         }
7110 }
7111
7112 /****************************************************************
7113  _spoolss_FindClosePrinterNotify
7114 ****************************************************************/
7115
7116 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7117                                        struct spoolss_FindClosePrinterNotify *r)
7118 {
7119         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7120
7121         if (!Printer) {
7122                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7123                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7124                 return WERR_BADFID;
7125         }
7126
7127         if (Printer->notify.cli_chan != NULL &&
7128             Printer->notify.cli_chan->active_connections > 0) {
7129                 int snum = -1;
7130
7131                 if (Printer->printer_type == SPLHND_PRINTER) {
7132                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7133                                 return WERR_BADFID;
7134                         }
7135                 }
7136
7137                 srv_spoolss_replycloseprinter(snum, Printer);
7138         }
7139
7140         Printer->notify.flags=0;
7141         Printer->notify.options=0;
7142         Printer->notify.localmachine[0]='\0';
7143         Printer->notify.printerlocal=0;
7144         TALLOC_FREE(Printer->notify.option);
7145
7146         return WERR_OK;
7147 }
7148
7149 /****************************************************************
7150  _spoolss_AddJob
7151 ****************************************************************/
7152
7153 WERROR _spoolss_AddJob(struct pipes_struct *p,
7154                        struct spoolss_AddJob *r)
7155 {
7156         if (!r->in.buffer && (r->in.offered != 0)) {
7157                 return WERR_INVALID_PARAM;
7158         }
7159
7160         /* this is what a NT server returns for AddJob. AddJob must fail on
7161          * non-local printers */
7162
7163         if (r->in.level != 1) {
7164                 return WERR_UNKNOWN_LEVEL;
7165         }
7166
7167         return WERR_INVALID_PARAM;
7168 }
7169
7170 /****************************************************************************
7171 fill_job_info1
7172 ****************************************************************************/
7173
7174 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7175                              struct spoolss_JobInfo1 *r,
7176                              const print_queue_struct *queue,
7177                              uint32_t jobid,
7178                              int position, int snum,
7179                              struct spoolss_PrinterInfo2 *pinfo2)
7180 {
7181         struct tm *t;
7182
7183         t = gmtime(&queue->time);
7184
7185         r->job_id               = jobid;
7186
7187         r->printer_name         = lp_servicename(mem_ctx, snum);
7188         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7189         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7190         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7191         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7192         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7193         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7194         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7195         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7196         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7197         r->text_status          = talloc_strdup(mem_ctx, "");
7198         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7199
7200         r->status               = nt_printj_status(queue->status);
7201         r->priority             = queue->priority;
7202         r->position             = position;
7203         r->total_pages          = queue->page_count;
7204         r->pages_printed        = 0; /* ??? */
7205
7206         init_systemtime(&r->submitted, t);
7207
7208         return WERR_OK;
7209 }
7210
7211 /****************************************************************************
7212 fill_job_info2
7213 ****************************************************************************/
7214
7215 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7216                              struct spoolss_JobInfo2 *r,
7217                              const print_queue_struct *queue,
7218                              uint32_t jobid,
7219                              int position, int snum,
7220                              struct spoolss_PrinterInfo2 *pinfo2,
7221                              struct spoolss_DeviceMode *devmode)
7222 {
7223         struct tm *t;
7224
7225         t = gmtime(&queue->time);
7226
7227         r->job_id               = jobid;
7228
7229         r->printer_name         = lp_servicename(mem_ctx, snum);
7230         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7231         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7232         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7233         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7234         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7235         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7236         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7237         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7238         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7239         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7240         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7241         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7242         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7243         r->parameters           = talloc_strdup(mem_ctx, "");
7244         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7245         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7246         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7247
7248         r->devmode              = devmode;
7249
7250         r->text_status          = talloc_strdup(mem_ctx, "");
7251         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7252
7253         r->secdesc              = NULL;
7254
7255         r->status               = nt_printj_status(queue->status);
7256         r->priority             = queue->priority;
7257         r->position             = position;
7258         r->start_time           = 0;
7259         r->until_time           = 0;
7260         r->total_pages          = queue->page_count;
7261         r->size                 = queue->size;
7262         init_systemtime(&r->submitted, t);
7263         r->time                 = 0;
7264         r->pages_printed        = 0; /* ??? */
7265
7266         return WERR_OK;
7267 }
7268
7269 /****************************************************************************
7270  Enumjobs at level 1.
7271 ****************************************************************************/
7272
7273 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7274                               const print_queue_struct *queue,
7275                               uint32_t num_queues, int snum,
7276                               struct spoolss_PrinterInfo2 *pinfo2,
7277                               union spoolss_JobInfo **info_p,
7278                               uint32_t *count)
7279 {
7280         union spoolss_JobInfo *info;
7281         int i;
7282         WERROR result = WERR_OK;
7283         uint32_t num_filled;
7284         struct tdb_print_db *pdb;
7285
7286         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7287         if (info == NULL) {
7288                 result = WERR_NOMEM;
7289                 goto err_out;
7290         }
7291
7292         pdb = get_print_db_byname(pinfo2->sharename);
7293         if (pdb == NULL) {
7294                 result = WERR_INVALID_PARAM;
7295                 goto err_info_free;
7296         }
7297
7298         num_filled = 0;
7299         for (i = 0; i < num_queues; i++) {
7300                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7301                 if (jobid == (uint32_t)-1) {
7302                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7303                         continue;
7304                 }
7305
7306                 result = fill_job_info1(info,
7307                                         &info[num_filled].info1,
7308                                         &queue[i],
7309                                         jobid,
7310                                         i,
7311                                         snum,
7312                                         pinfo2);
7313                 if (!W_ERROR_IS_OK(result)) {
7314                         goto err_pdb_drop;
7315                 }
7316
7317                 num_filled++;
7318         }
7319
7320         release_print_db(pdb);
7321         *info_p = info;
7322         *count = num_filled;
7323
7324         return WERR_OK;
7325
7326 err_pdb_drop:
7327         release_print_db(pdb);
7328 err_info_free:
7329         TALLOC_FREE(info);
7330 err_out:
7331         *count = 0;
7332         return result;
7333 }
7334
7335 /****************************************************************************
7336  Enumjobs at level 2.
7337 ****************************************************************************/
7338
7339 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7340                               const print_queue_struct *queue,
7341                               uint32_t num_queues, int snum,
7342                               struct spoolss_PrinterInfo2 *pinfo2,
7343                               union spoolss_JobInfo **info_p,
7344                               uint32_t *count)
7345 {
7346         union spoolss_JobInfo *info;
7347         int i;
7348         WERROR result = WERR_OK;
7349         uint32_t num_filled;
7350         struct tdb_print_db *pdb;
7351
7352         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7353         if (info == NULL) {
7354                 result = WERR_NOMEM;
7355                 goto err_out;
7356         }
7357
7358         pdb = get_print_db_byname(pinfo2->sharename);
7359         if (pdb == NULL) {
7360                 result = WERR_INVALID_PARAM;
7361                 goto err_info_free;
7362         }
7363
7364         num_filled = 0;
7365         for (i = 0; i< num_queues; i++) {
7366                 struct spoolss_DeviceMode *devmode;
7367                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7368                 if (jobid == (uint32_t)-1) {
7369                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7370                         continue;
7371                 }
7372
7373                 result = spoolss_create_default_devmode(info,
7374                                                         pinfo2->printername,
7375                                                         &devmode);
7376                 if (!W_ERROR_IS_OK(result)) {
7377                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7378                         goto err_pdb_drop;
7379                 }
7380
7381                 result = fill_job_info2(info,
7382                                         &info[num_filled].info2,
7383                                         &queue[i],
7384                                         jobid,
7385                                         i,
7386                                         snum,
7387                                         pinfo2,
7388                                         devmode);
7389                 if (!W_ERROR_IS_OK(result)) {
7390                         goto err_pdb_drop;
7391                 }
7392                 num_filled++;
7393         }
7394
7395         release_print_db(pdb);
7396         *info_p = info;
7397         *count = num_filled;
7398
7399         return WERR_OK;
7400
7401 err_pdb_drop:
7402         release_print_db(pdb);
7403 err_info_free:
7404         TALLOC_FREE(info);
7405 err_out:
7406         *count = 0;
7407         return result;
7408 }
7409
7410 /****************************************************************************
7411  Enumjobs at level 3.
7412 ****************************************************************************/
7413
7414 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7415                               const print_queue_struct *queue,
7416                               uint32_t num_queues, int snum,
7417                               struct spoolss_PrinterInfo2 *pinfo2,
7418                               union spoolss_JobInfo **info_p,
7419                               uint32_t *count)
7420 {
7421         union spoolss_JobInfo *info;
7422         int i;
7423         WERROR result = WERR_OK;
7424         uint32_t num_filled;
7425         struct tdb_print_db *pdb;
7426
7427         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7428         if (info == NULL) {
7429                 result = WERR_NOMEM;
7430                 goto err_out;
7431         }
7432
7433         pdb = get_print_db_byname(pinfo2->sharename);
7434         if (pdb == NULL) {
7435                 result = WERR_INVALID_PARAM;
7436                 goto err_info_free;
7437         }
7438
7439         num_filled = 0;
7440         for (i = 0; i < num_queues; i++) {
7441                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7442                 if (jobid == (uint32_t)-1) {
7443                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7444                         continue;
7445                 }
7446
7447                 info[num_filled].info3.job_id = jobid;
7448                 /* next_job_id is overwritten on next iteration */
7449                 info[num_filled].info3.next_job_id = 0;
7450                 info[num_filled].info3.reserved = 0;
7451
7452                 if (num_filled > 0) {
7453                         info[num_filled - 1].info3.next_job_id = jobid;
7454                 }
7455                 num_filled++;
7456         }
7457
7458         release_print_db(pdb);
7459         *info_p = info;
7460         *count = num_filled;
7461
7462         return WERR_OK;
7463
7464 err_info_free:
7465         TALLOC_FREE(info);
7466 err_out:
7467         *count = 0;
7468         return result;
7469 }
7470
7471 /****************************************************************
7472  _spoolss_EnumJobs
7473 ****************************************************************/
7474
7475 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7476                          struct spoolss_EnumJobs *r)
7477 {
7478         WERROR result;
7479         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7480         int snum;
7481         print_status_struct prt_status;
7482         print_queue_struct *queue = NULL;
7483         uint32_t count;
7484
7485         /* that's an [in out] buffer */
7486
7487         if (!r->in.buffer && (r->in.offered != 0)) {
7488                 return WERR_INVALID_PARAM;
7489         }
7490
7491         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7492                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7493                 return WERR_UNKNOWN_LEVEL;
7494         }
7495
7496         DEBUG(4,("_spoolss_EnumJobs\n"));
7497
7498         *r->out.needed = 0;
7499         *r->out.count = 0;
7500         *r->out.info = NULL;
7501
7502         /* lookup the printer snum and tdb entry */
7503
7504         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7505                 return WERR_BADFID;
7506         }
7507
7508         result = winreg_get_printer_internal(p->mem_ctx,
7509                                     get_session_info_system(),
7510                                     p->msg_ctx,
7511                                     lp_const_servicename(snum),
7512                                     &pinfo2);
7513         if (!W_ERROR_IS_OK(result)) {
7514                 return result;
7515         }
7516
7517         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7518         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7519                 count, prt_status.status, prt_status.message));
7520
7521         if (count == 0) {
7522                 SAFE_FREE(queue);
7523                 TALLOC_FREE(pinfo2);
7524                 return WERR_OK;
7525         }
7526
7527         switch (r->in.level) {
7528         case 1:
7529                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7530                                          pinfo2, r->out.info, r->out.count);
7531                 break;
7532         case 2:
7533                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7534                                          pinfo2, r->out.info, r->out.count);
7535                 break;
7536         case 3:
7537                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7538                                          pinfo2, r->out.info, r->out.count);
7539                 break;
7540         default:
7541                 SMB_ASSERT(false);      /* level checked on entry */
7542                 break;
7543         }
7544
7545         SAFE_FREE(queue);
7546         TALLOC_FREE(pinfo2);
7547
7548         if (!W_ERROR_IS_OK(result)) {
7549                 return result;
7550         }
7551
7552         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7553                                                      spoolss_EnumJobs,
7554                                                      *r->out.info, r->in.level,
7555                                                      *r->out.count);
7556         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7557         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7558
7559         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7560 }
7561
7562 /****************************************************************
7563  _spoolss_ScheduleJob
7564 ****************************************************************/
7565
7566 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7567                             struct spoolss_ScheduleJob *r)
7568 {
7569         return WERR_OK;
7570 }
7571
7572 /****************************************************************
7573 ****************************************************************/
7574
7575 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7576                                struct messaging_context *msg_ctx,
7577                                const char *printer_name,
7578                                uint32_t job_id,
7579                                struct spoolss_SetJobInfo1 *r)
7580 {
7581         char *old_doc_name;
7582
7583         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7584                 return WERR_BADFID;
7585         }
7586
7587         if (strequal(old_doc_name, r->document_name)) {
7588                 return WERR_OK;
7589         }
7590
7591         if (!print_job_set_name(server_event_context(), msg_ctx,
7592                                 printer_name, job_id, r->document_name)) {
7593                 return WERR_BADFID;
7594         }
7595
7596         return WERR_OK;
7597 }
7598
7599 /****************************************************************
7600  _spoolss_SetJob
7601 ****************************************************************/
7602
7603 WERROR _spoolss_SetJob(struct pipes_struct *p,
7604                        struct spoolss_SetJob *r)
7605 {
7606         const struct auth_session_info *session_info = p->session_info;
7607         int snum;
7608         WERROR errcode = WERR_BADFUNC;
7609
7610         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7611                 return WERR_BADFID;
7612         }
7613
7614         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7615                 return WERR_INVALID_PRINTER_NAME;
7616         }
7617
7618         switch (r->in.command) {
7619         case SPOOLSS_JOB_CONTROL_CANCEL:
7620         case SPOOLSS_JOB_CONTROL_DELETE:
7621                 errcode = print_job_delete(session_info, p->msg_ctx,
7622                                            snum, r->in.job_id);
7623                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7624                         errcode = WERR_OK;
7625                 }
7626                 break;
7627         case SPOOLSS_JOB_CONTROL_PAUSE:
7628                 errcode = print_job_pause(session_info, p->msg_ctx,
7629                                           snum, r->in.job_id);
7630                 break;
7631         case SPOOLSS_JOB_CONTROL_RESTART:
7632         case SPOOLSS_JOB_CONTROL_RESUME:
7633                 errcode = print_job_resume(session_info, p->msg_ctx,
7634                                            snum, r->in.job_id);
7635                 break;
7636         case SPOOLSS_JOB_CONTROL_NOOP:
7637                 errcode = WERR_OK;
7638                 break;
7639         default:
7640                 return WERR_UNKNOWN_LEVEL;
7641         }
7642
7643         if (!W_ERROR_IS_OK(errcode)) {
7644                 return errcode;
7645         }
7646
7647         if (r->in.ctr == NULL) {
7648                 return errcode;
7649         }
7650
7651         switch (r->in.ctr->level) {
7652         case 1:
7653                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7654                                            lp_const_servicename(snum),
7655                                            r->in.job_id,
7656                                            r->in.ctr->info.info1);
7657                 break;
7658         case 2:
7659         case 3:
7660         case 4:
7661         default:
7662                 return WERR_UNKNOWN_LEVEL;
7663         }
7664
7665         return errcode;
7666 }
7667
7668 /****************************************************************************
7669  Enumerates all printer drivers by level and architecture.
7670 ****************************************************************************/
7671
7672 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7673                                                        const struct auth_session_info *session_info,
7674                                                        struct messaging_context *msg_ctx,
7675                                                        const char *servername,
7676                                                        const char *architecture,
7677                                                        uint32_t level,
7678                                                        union spoolss_DriverInfo **info_p,
7679                                                        uint32_t *count_p)
7680 {
7681         int i;
7682         uint32_t version;
7683         struct spoolss_DriverInfo8 *driver;
7684         union spoolss_DriverInfo *info = NULL;
7685         uint32_t count = 0;
7686         WERROR result = WERR_OK;
7687         uint32_t num_drivers;
7688         const char **drivers;
7689         struct dcerpc_binding_handle *b;
7690         TALLOC_CTX *tmp_ctx = NULL;
7691
7692         *count_p = 0;
7693         *info_p = NULL;
7694
7695         tmp_ctx = talloc_new(mem_ctx);
7696         if (!tmp_ctx) {
7697                 return WERR_NOMEM;
7698         }
7699
7700         result = winreg_printer_binding_handle(tmp_ctx,
7701                                                session_info,
7702                                                msg_ctx,
7703                                                &b);
7704         if (!W_ERROR_IS_OK(result)) {
7705                 goto out;
7706         }
7707
7708         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7709                 result = winreg_get_driver_list(tmp_ctx, b,
7710                                                 architecture, version,
7711                                                 &num_drivers, &drivers);
7712                 if (!W_ERROR_IS_OK(result)) {
7713                         goto out;
7714                 }
7715                 DEBUG(4, ("we have:[%d] drivers in environment"
7716                           " [%s] and version [%d]\n",
7717                           num_drivers, architecture, version));
7718
7719                 if (num_drivers != 0) {
7720                         info = talloc_realloc(tmp_ctx, info,
7721                                                     union spoolss_DriverInfo,
7722                                                     count + num_drivers);
7723                         if (!info) {
7724                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7725                                         "failed to enlarge driver info buffer!\n"));
7726                                 result = WERR_NOMEM;
7727                                 goto out;
7728                         }
7729                 }
7730
7731                 for (i = 0; i < num_drivers; i++) {
7732                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7733
7734                         result = winreg_get_driver(tmp_ctx, b,
7735                                                    architecture, drivers[i],
7736                                                    version, &driver);
7737                         if (!W_ERROR_IS_OK(result)) {
7738                                 goto out;
7739                         }
7740
7741                         switch (level) {
7742                         case 1:
7743                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7744                                                                    driver, servername);
7745                                 break;
7746                         case 2:
7747                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7748                                                                    driver, servername);
7749                                 break;
7750                         case 3:
7751                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7752                                                                    driver, servername);
7753                                 break;
7754                         case 4:
7755                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7756                                                                    driver, servername);
7757                                 break;
7758                         case 5:
7759                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7760                                                                    driver, servername);
7761                                 break;
7762                         case 6:
7763                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7764                                                                    driver, servername);
7765                                 break;
7766                         case 8:
7767                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7768                                                                    driver, servername);
7769                                 break;
7770                         default:
7771                                 result = WERR_UNKNOWN_LEVEL;
7772                                 break;
7773                         }
7774
7775                         TALLOC_FREE(driver);
7776
7777                         if (!W_ERROR_IS_OK(result)) {
7778                                 goto out;
7779                         }
7780                 }
7781
7782                 count += num_drivers;
7783                 TALLOC_FREE(drivers);
7784         }
7785
7786 out:
7787         if (W_ERROR_IS_OK(result)) {
7788                 *info_p = talloc_move(mem_ctx, &info);
7789                 *count_p = count;
7790         }
7791
7792         talloc_free(tmp_ctx);
7793         return result;
7794 }
7795
7796 /****************************************************************************
7797  Enumerates all printer drivers by level.
7798 ****************************************************************************/
7799
7800 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7801                                        const struct auth_session_info *session_info,
7802                                        struct messaging_context *msg_ctx,
7803                                        const char *servername,
7804                                        const char *architecture,
7805                                        uint32_t level,
7806                                        union spoolss_DriverInfo **info_p,
7807                                        uint32_t *count_p)
7808 {
7809         uint32_t a,i;
7810         WERROR result = WERR_OK;
7811
7812         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7813
7814                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7815
7816                         union spoolss_DriverInfo *info = NULL;
7817                         uint32_t count = 0;
7818
7819                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7820                                                                           session_info,
7821                                                                           msg_ctx,
7822                                                                           servername,
7823                                                                           archi_table[a].long_archi,
7824                                                                           level,
7825                                                                           &info,
7826                                                                           &count);
7827                         if (!W_ERROR_IS_OK(result)) {
7828                                 continue;
7829                         }
7830
7831                         for (i=0; i < count; i++) {
7832                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7833                                              info[i], info_p, count_p);
7834                         }
7835                 }
7836
7837                 return result;
7838         }
7839
7840         return enumprinterdrivers_level_by_architecture(mem_ctx,
7841                                                         session_info,
7842                                                         msg_ctx,
7843                                                         servername,
7844                                                         architecture,
7845                                                         level,
7846                                                         info_p,
7847                                                         count_p);
7848 }
7849
7850 /****************************************************************
7851  _spoolss_EnumPrinterDrivers
7852 ****************************************************************/
7853
7854 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7855                                    struct spoolss_EnumPrinterDrivers *r)
7856 {
7857         const char *cservername;
7858         WERROR result;
7859
7860         /* that's an [in out] buffer */
7861
7862         if (!r->in.buffer && (r->in.offered != 0)) {
7863                 return WERR_INVALID_PARAM;
7864         }
7865
7866         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7867
7868         *r->out.needed = 0;
7869         *r->out.count = 0;
7870         *r->out.info = NULL;
7871
7872         cservername = canon_servername(r->in.server);
7873
7874         if (!is_myname_or_ipaddr(cservername)) {
7875                 return WERR_UNKNOWN_PRINTER_DRIVER;
7876         }
7877
7878         result = enumprinterdrivers_level(p->mem_ctx,
7879                                           get_session_info_system(),
7880                                           p->msg_ctx,
7881                                           cservername,
7882                                           r->in.environment,
7883                                           r->in.level,
7884                                           r->out.info,
7885                                           r->out.count);
7886         if (!W_ERROR_IS_OK(result)) {
7887                 return result;
7888         }
7889
7890         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7891                                                      spoolss_EnumPrinterDrivers,
7892                                                      *r->out.info, r->in.level,
7893                                                      *r->out.count);
7894         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7895         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7896
7897         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7898 }
7899
7900 /****************************************************************
7901  _spoolss_EnumForms
7902 ****************************************************************/
7903
7904 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7905                           struct spoolss_EnumForms *r)
7906 {
7907         WERROR result;
7908
7909         *r->out.count = 0;
7910         *r->out.needed = 0;
7911         *r->out.info = NULL;
7912
7913         /* that's an [in out] buffer */
7914
7915         if (!r->in.buffer && (r->in.offered != 0) ) {
7916                 return WERR_INVALID_PARAM;
7917         }
7918
7919         DEBUG(4,("_spoolss_EnumForms\n"));
7920         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7921         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7922
7923         switch (r->in.level) {
7924         case 1:
7925                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7926                                                    get_session_info_system(),
7927                                                    p->msg_ctx,
7928                                                    r->out.count,
7929                                                    r->out.info);
7930                 break;
7931         default:
7932                 result = WERR_UNKNOWN_LEVEL;
7933                 break;
7934         }
7935
7936         if (!W_ERROR_IS_OK(result)) {
7937                 return result;
7938         }
7939
7940         if (*r->out.count == 0) {
7941                 return WERR_NO_MORE_ITEMS;
7942         }
7943
7944         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7945                                                      spoolss_EnumForms,
7946                                                      *r->out.info, r->in.level,
7947                                                      *r->out.count);
7948         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7949         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7950
7951         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7952 }
7953
7954 /****************************************************************
7955  _spoolss_GetForm
7956 ****************************************************************/
7957
7958 WERROR _spoolss_GetForm(struct pipes_struct *p,
7959                         struct spoolss_GetForm *r)
7960 {
7961         WERROR result;
7962
7963         /* that's an [in out] buffer */
7964
7965         if (!r->in.buffer && (r->in.offered != 0)) {
7966                 TALLOC_FREE(r->out.info);
7967                 return WERR_INVALID_PARAM;
7968         }
7969
7970         DEBUG(4,("_spoolss_GetForm\n"));
7971         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7972         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7973
7974         switch (r->in.level) {
7975         case 1:
7976                 result = winreg_printer_getform1_internal(p->mem_ctx,
7977                                                  get_session_info_system(),
7978                                                  p->msg_ctx,
7979                                                  r->in.form_name,
7980                                                  &r->out.info->info1);
7981                 break;
7982         default:
7983                 result = WERR_UNKNOWN_LEVEL;
7984                 break;
7985         }
7986
7987         if (!W_ERROR_IS_OK(result)) {
7988                 TALLOC_FREE(r->out.info);
7989                 return result;
7990         }
7991
7992         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7993                                                r->out.info, r->in.level);
7994         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7995
7996         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7997 }
7998
7999 /****************************************************************************
8000 ****************************************************************************/
8001
8002 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8003                           struct spoolss_PortInfo1 *r,
8004                           const char *name)
8005 {
8006         r->port_name = talloc_strdup(mem_ctx, name);
8007         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8008
8009         return WERR_OK;
8010 }
8011
8012 /****************************************************************************
8013  TODO: This probably needs distinguish between TCP/IP and Local ports
8014  somehow.
8015 ****************************************************************************/
8016
8017 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8018                           struct spoolss_PortInfo2 *r,
8019                           const char *name)
8020 {
8021         r->port_name = talloc_strdup(mem_ctx, name);
8022         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8023
8024         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8025         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8026
8027         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8028         W_ERROR_HAVE_NO_MEMORY(r->description);
8029
8030         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8031         r->reserved = 0;
8032
8033         return WERR_OK;
8034 }
8035
8036
8037 /****************************************************************************
8038  wrapper around the enumer ports command
8039 ****************************************************************************/
8040
8041 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8042 {
8043         char *cmd = lp_enumports_command(talloc_tos());
8044         char **qlines = NULL;
8045         char *command = NULL;
8046         int numlines;
8047         int ret;
8048         int fd;
8049
8050         *count = 0;
8051         *lines = NULL;
8052
8053         /* if no hook then just fill in the default port */
8054
8055         if ( !*cmd ) {
8056                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8057                         return WERR_NOMEM;
8058                 }
8059                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8060                         TALLOC_FREE(qlines);
8061                         return WERR_NOMEM;
8062                 }
8063                 qlines[1] = NULL;
8064                 numlines = 1;
8065         }
8066         else {
8067                 /* we have a valid enumport command */
8068
8069                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8070                 if (!command) {
8071                         return WERR_NOMEM;
8072                 }
8073
8074                 DEBUG(10,("Running [%s]\n", command));
8075                 ret = smbrun(command, &fd);
8076                 DEBUG(10,("Returned [%d]\n", ret));
8077                 TALLOC_FREE(command);
8078                 if (ret != 0) {
8079                         if (fd != -1) {
8080                                 close(fd);
8081                         }
8082                         return WERR_ACCESS_DENIED;
8083                 }
8084
8085                 numlines = 0;
8086                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
8087                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8088                 close(fd);
8089         }
8090
8091         *count = numlines;
8092         *lines = qlines;
8093
8094         return WERR_OK;
8095 }
8096
8097 /****************************************************************************
8098  enumports level 1.
8099 ****************************************************************************/
8100
8101 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8102                                 union spoolss_PortInfo **info_p,
8103                                 uint32_t *count)
8104 {
8105         union spoolss_PortInfo *info = NULL;
8106         int i=0;
8107         WERROR result = WERR_OK;
8108         char **qlines = NULL;
8109         int numlines = 0;
8110
8111         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8112         if (!W_ERROR_IS_OK(result)) {
8113                 goto out;
8114         }
8115
8116         if (numlines) {
8117                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8118                 if (!info) {
8119                         DEBUG(10,("Returning WERR_NOMEM\n"));
8120                         result = WERR_NOMEM;
8121                         goto out;
8122                 }
8123
8124                 for (i=0; i<numlines; i++) {
8125                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8126                         result = fill_port_1(info, &info[i].info1, qlines[i]);
8127                         if (!W_ERROR_IS_OK(result)) {
8128                                 goto out;
8129                         }
8130                 }
8131         }
8132         TALLOC_FREE(qlines);
8133
8134 out:
8135         if (!W_ERROR_IS_OK(result)) {
8136                 TALLOC_FREE(info);
8137                 TALLOC_FREE(qlines);
8138                 *count = 0;
8139                 *info_p = NULL;
8140                 return result;
8141         }
8142
8143         *info_p = info;
8144         *count = numlines;
8145
8146         return WERR_OK;
8147 }
8148
8149 /****************************************************************************
8150  enumports level 2.
8151 ****************************************************************************/
8152
8153 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8154                                 union spoolss_PortInfo **info_p,
8155                                 uint32_t *count)
8156 {
8157         union spoolss_PortInfo *info = NULL;
8158         int i=0;
8159         WERROR result = WERR_OK;
8160         char **qlines = NULL;
8161         int numlines = 0;
8162
8163         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8164         if (!W_ERROR_IS_OK(result)) {
8165                 goto out;
8166         }
8167
8168         if (numlines) {
8169                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8170                 if (!info) {
8171                         DEBUG(10,("Returning WERR_NOMEM\n"));
8172                         result = WERR_NOMEM;
8173                         goto out;
8174                 }
8175
8176                 for (i=0; i<numlines; i++) {
8177                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8178                         result = fill_port_2(info, &info[i].info2, qlines[i]);
8179                         if (!W_ERROR_IS_OK(result)) {
8180                                 goto out;
8181                         }
8182                 }
8183         }
8184         TALLOC_FREE(qlines);
8185
8186 out:
8187         if (!W_ERROR_IS_OK(result)) {
8188                 TALLOC_FREE(info);
8189                 TALLOC_FREE(qlines);
8190                 *count = 0;
8191                 *info_p = NULL;
8192                 return result;
8193         }
8194
8195         *info_p = info;
8196         *count = numlines;
8197
8198         return WERR_OK;
8199 }
8200
8201 /****************************************************************
8202  _spoolss_EnumPorts
8203 ****************************************************************/
8204
8205 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8206                           struct spoolss_EnumPorts *r)
8207 {
8208         WERROR result;
8209
8210         /* that's an [in out] buffer */
8211
8212         if (!r->in.buffer && (r->in.offered != 0)) {
8213                 return WERR_INVALID_PARAM;
8214         }
8215
8216         DEBUG(4,("_spoolss_EnumPorts\n"));
8217
8218         *r->out.count = 0;
8219         *r->out.needed = 0;
8220         *r->out.info = NULL;
8221
8222         switch (r->in.level) {
8223         case 1:
8224                 result = enumports_level_1(p->mem_ctx, r->out.info,
8225                                            r->out.count);
8226                 break;
8227         case 2:
8228                 result = enumports_level_2(p->mem_ctx, r->out.info,
8229                                            r->out.count);
8230                 break;
8231         default:
8232                 return WERR_UNKNOWN_LEVEL;
8233         }
8234
8235         if (!W_ERROR_IS_OK(result)) {
8236                 return result;
8237         }
8238
8239         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8240                                                      spoolss_EnumPorts,
8241                                                      *r->out.info, r->in.level,
8242                                                      *r->out.count);
8243         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8244         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8245
8246         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8247 }
8248
8249 /****************************************************************************
8250 ****************************************************************************/
8251
8252 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8253                                            const char *server,
8254                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8255                                            struct spoolss_DeviceMode *devmode,
8256                                            struct security_descriptor *secdesc,
8257                                            struct spoolss_UserLevelCtr *user_ctr,
8258                                            struct policy_handle *handle)
8259 {
8260         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8261         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8262         int     snum;
8263         WERROR err = WERR_OK;
8264
8265         /* samba does not have a concept of local, non-shared printers yet, so
8266          * make sure we always setup sharename - gd */
8267         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8268             (info2->printername != NULL && info2->printername[0] != '\0')) {
8269                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8270                         "no sharename has been set, setting printername %s as sharename\n",
8271                         info2->printername));
8272                 info2->sharename = info2->printername;
8273         }
8274
8275         /* check to see if the printer already exists */
8276         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8277                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8278                         info2->sharename));
8279                 return WERR_PRINTER_ALREADY_EXISTS;
8280         }
8281
8282         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8283                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8284                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8285                                 info2->printername));
8286                         return WERR_PRINTER_ALREADY_EXISTS;
8287                 }
8288         }
8289
8290         /* validate printer info struct */
8291         if (!info2->printername || strlen(info2->printername) == 0) {
8292                 return WERR_INVALID_PRINTER_NAME;
8293         }
8294         if (!info2->portname || strlen(info2->portname) == 0) {
8295                 return WERR_UNKNOWN_PORT;
8296         }
8297         if (!info2->drivername || strlen(info2->drivername) == 0) {
8298                 return WERR_UNKNOWN_PRINTER_DRIVER;
8299         }
8300         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8301                 return WERR_UNKNOWN_PRINTPROCESSOR;
8302         }
8303
8304         /* FIXME!!!  smbd should check to see if the driver is installed before
8305            trying to add a printer like this  --jerry */
8306
8307         if (*lp_addprinter_command(talloc_tos()) ) {
8308                 char *raddr;
8309
8310                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8311                                                          p->mem_ctx);
8312                 if (raddr == NULL) {
8313                         return WERR_NOMEM;
8314                 }
8315
8316                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8317                                        info2, raddr,
8318                                        p->msg_ctx) ) {
8319                         return WERR_ACCESS_DENIED;
8320                 }
8321         } else {
8322                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8323                         "smb.conf parameter \"addprinter command\" is defined. This "
8324                         "parameter must exist for this call to succeed\n",
8325                         info2->sharename ));
8326         }
8327
8328         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8329                 return WERR_ACCESS_DENIED;
8330         }
8331
8332         /* you must be a printer admin to add a new printer */
8333         if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8334                                               p->msg_ctx,
8335                                               snum,
8336                                               PRINTER_ACCESS_ADMINISTER))) {
8337                 return WERR_ACCESS_DENIED;
8338         }
8339
8340         /*
8341          * Do sanity check on the requested changes for Samba.
8342          */
8343
8344         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8345                 return WERR_INVALID_PARAM;
8346         }
8347
8348         if (devmode == NULL) {
8349                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8350         }
8351
8352         err = update_dsspooler(p->mem_ctx,
8353                                get_session_info_system(),
8354                                p->msg_ctx,
8355                                0,
8356                                info2,
8357                                NULL);
8358         if (!W_ERROR_IS_OK(err)) {
8359                 return err;
8360         }
8361
8362         err = winreg_update_printer_internal(p->mem_ctx,
8363                                     get_session_info_system(),
8364                                     p->msg_ctx,
8365                                     info2->sharename,
8366                                     info2_mask,
8367                                     info2,
8368                                     devmode,
8369                                     secdesc);
8370         if (!W_ERROR_IS_OK(err)) {
8371                 return err;
8372         }
8373
8374         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8375         if (!W_ERROR_IS_OK(err)) {
8376                 /* Handle open failed - remove addition. */
8377                 ZERO_STRUCTP(handle);
8378                 return err;
8379         }
8380
8381         return WERR_OK;
8382 }
8383
8384 /****************************************************************
8385  _spoolss_AddPrinterEx
8386 ****************************************************************/
8387
8388 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8389                              struct spoolss_AddPrinterEx *r)
8390 {
8391         switch (r->in.info_ctr->level) {
8392         case 1:
8393                 /* we don't handle yet */
8394                 /* but I know what to do ... */
8395                 return WERR_UNKNOWN_LEVEL;
8396         case 2:
8397                 return spoolss_addprinterex_level_2(p, r->in.server,
8398                                                     r->in.info_ctr,
8399                                                     r->in.devmode_ctr->devmode,
8400                                                     r->in.secdesc_ctr->sd,
8401                                                     r->in.userlevel_ctr,
8402                                                     r->out.handle);
8403         default:
8404                 return WERR_UNKNOWN_LEVEL;
8405         }
8406 }
8407
8408 /****************************************************************
8409  _spoolss_AddPrinter
8410 ****************************************************************/
8411
8412 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8413                            struct spoolss_AddPrinter *r)
8414 {
8415         struct spoolss_AddPrinterEx a;
8416         struct spoolss_UserLevelCtr userlevel_ctr;
8417
8418         ZERO_STRUCT(userlevel_ctr);
8419
8420         userlevel_ctr.level = 1;
8421
8422         a.in.server             = r->in.server;
8423         a.in.info_ctr           = r->in.info_ctr;
8424         a.in.devmode_ctr        = r->in.devmode_ctr;
8425         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8426         a.in.userlevel_ctr      = &userlevel_ctr;
8427         a.out.handle            = r->out.handle;
8428
8429         return _spoolss_AddPrinterEx(p, &a);
8430 }
8431
8432 /****************************************************************
8433  _spoolss_AddPrinterDriverEx
8434 ****************************************************************/
8435
8436 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8437                                    struct spoolss_AddPrinterDriverEx *r)
8438 {
8439         WERROR err = WERR_OK;
8440         const char *driver_name = NULL;
8441         uint32_t version;
8442         const char *fn;
8443
8444         switch (p->opnum) {
8445                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8446                         fn = "_spoolss_AddPrinterDriver";
8447                         break;
8448                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8449                         fn = "_spoolss_AddPrinterDriverEx";
8450                         break;
8451                 default:
8452                         return WERR_INVALID_PARAM;
8453         }
8454
8455         /*
8456          * we only support the semantics of AddPrinterDriver()
8457          * i.e. only copy files that are newer than existing ones
8458          */
8459
8460         if (r->in.flags == 0) {
8461                 return WERR_INVALID_PARAM;
8462         }
8463
8464         if (r->in.flags != APD_COPY_NEW_FILES) {
8465                 return WERR_ACCESS_DENIED;
8466         }
8467
8468         /* FIXME */
8469         if (r->in.info_ctr->level != 3 &&
8470             r->in.info_ctr->level != 6 &&
8471             r->in.info_ctr->level != 8) {
8472                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8473                         r->in.info_ctr->level));
8474                 return WERR_UNKNOWN_LEVEL;
8475         }
8476
8477         DEBUG(5,("Cleaning driver's information\n"));
8478         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8479         if (!W_ERROR_IS_OK(err))
8480                 goto done;
8481
8482         DEBUG(5,("Moving driver to final destination\n"));
8483         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8484         if (!W_ERROR_IS_OK(err)) {
8485                 goto done;
8486         }
8487
8488         err = winreg_add_driver_internal(p->mem_ctx,
8489                                 get_session_info_system(),
8490                                 p->msg_ctx,
8491                                 r->in.info_ctr,
8492                                 &driver_name,
8493                                 &version);
8494         if (!W_ERROR_IS_OK(err)) {
8495                 goto done;
8496         }
8497
8498         /*
8499          * I think this is where he DrvUpgradePrinter() hook would be
8500          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8501          * server.  Right now, we just need to send ourselves a message
8502          * to update each printer bound to this driver.   --jerry
8503          */
8504
8505         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8506                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8507                         fn, driver_name));
8508         }
8509
8510 done:
8511         return err;
8512 }
8513
8514 /****************************************************************
8515  _spoolss_AddPrinterDriver
8516 ****************************************************************/
8517
8518 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8519                                  struct spoolss_AddPrinterDriver *r)
8520 {
8521         struct spoolss_AddPrinterDriverEx a;
8522
8523         switch (r->in.info_ctr->level) {
8524         case 2:
8525         case 3:
8526         case 4:
8527         case 5:
8528                 break;
8529         default:
8530                 return WERR_UNKNOWN_LEVEL;
8531         }
8532
8533         a.in.servername         = r->in.servername;
8534         a.in.info_ctr           = r->in.info_ctr;
8535         a.in.flags              = APD_COPY_NEW_FILES;
8536
8537         return _spoolss_AddPrinterDriverEx(p, &a);
8538 }
8539
8540 /****************************************************************************
8541 ****************************************************************************/
8542
8543 struct _spoolss_paths {
8544         int type;
8545         const char *share;
8546         const char *dir;
8547 };
8548
8549 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8550
8551 static const struct _spoolss_paths spoolss_paths[]= {
8552         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8553         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8554 };
8555
8556 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8557                                           const char *servername,
8558                                           const char *environment,
8559                                           int component,
8560                                           char **path)
8561 {
8562         const char *pservername = NULL;
8563         const char *long_archi;
8564         const char *short_archi;
8565
8566         *path = NULL;
8567
8568         /* environment may be empty */
8569         if (environment && strlen(environment)) {
8570                 long_archi = environment;
8571         } else {
8572                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8573                                                   "spoolss", "architecture",
8574                                                   SPOOLSS_ARCHITECTURE_NT_X86);
8575         }
8576
8577         /* servername may be empty */
8578         if (servername && strlen(servername)) {
8579                 pservername = canon_servername(servername);
8580
8581                 if (!is_myname_or_ipaddr(pservername)) {
8582                         return WERR_INVALID_PARAM;
8583                 }
8584         }
8585
8586         if (!(short_archi = get_short_archi(long_archi))) {
8587                 return WERR_INVALID_ENVIRONMENT;
8588         }
8589
8590         switch (component) {
8591         case SPOOLSS_PRTPROCS_PATH:
8592         case SPOOLSS_DRIVER_PATH:
8593                 if (pservername) {
8594                         *path = talloc_asprintf(mem_ctx,
8595                                         "\\\\%s\\%s\\%s",
8596                                         pservername,
8597                                         spoolss_paths[component].share,
8598                                         short_archi);
8599                 } else {
8600                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8601                                         SPOOLSS_DEFAULT_SERVER_PATH,
8602                                         spoolss_paths[component].dir,
8603                                         short_archi);
8604                 }
8605                 break;
8606         default:
8607                 return WERR_INVALID_PARAM;
8608         }
8609
8610         if (!*path) {
8611                 return WERR_NOMEM;
8612         }
8613
8614         return WERR_OK;
8615 }
8616
8617 /****************************************************************************
8618 ****************************************************************************/
8619
8620 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8621                                           const char *servername,
8622                                           const char *environment,
8623                                           struct spoolss_DriverDirectoryInfo1 *r)
8624 {
8625         WERROR werr;
8626         char *path = NULL;
8627
8628         werr = compose_spoolss_server_path(mem_ctx,
8629                                            servername,
8630                                            environment,
8631                                            SPOOLSS_DRIVER_PATH,
8632                                            &path);
8633         if (!W_ERROR_IS_OK(werr)) {
8634                 return werr;
8635         }
8636
8637         DEBUG(4,("printer driver directory: [%s]\n", path));
8638
8639         r->directory_name = path;
8640
8641         return WERR_OK;
8642 }
8643
8644 /****************************************************************
8645  _spoolss_GetPrinterDriverDirectory
8646 ****************************************************************/
8647
8648 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8649                                           struct spoolss_GetPrinterDriverDirectory *r)
8650 {
8651         WERROR werror;
8652
8653         /* that's an [in out] buffer */
8654
8655         if (!r->in.buffer && (r->in.offered != 0)) {
8656                 TALLOC_FREE(r->out.info);
8657                 return WERR_INVALID_PARAM;
8658         }
8659
8660         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8661                 r->in.level));
8662
8663         *r->out.needed = 0;
8664
8665         /* r->in.level is ignored */
8666
8667         werror = getprinterdriverdir_level_1(p->mem_ctx,
8668                                              r->in.server,
8669                                              r->in.environment,
8670                                              &r->out.info->info1);
8671         if (!W_ERROR_IS_OK(werror)) {
8672                 TALLOC_FREE(r->out.info);
8673                 return werror;
8674         }
8675
8676         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8677                                                r->out.info, r->in.level);
8678         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8679
8680         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8681 }
8682
8683 /****************************************************************
8684  _spoolss_EnumPrinterData
8685 ****************************************************************/
8686
8687 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8688                                 struct spoolss_EnumPrinterData *r)
8689 {
8690         WERROR result;
8691         struct spoolss_EnumPrinterDataEx r2;
8692         uint32_t count;
8693         struct spoolss_PrinterEnumValues *info, *val = NULL;
8694         uint32_t needed;
8695
8696         r2.in.handle    = r->in.handle;
8697         r2.in.key_name  = "PrinterDriverData";
8698         r2.in.offered   = 0;
8699         r2.out.count    = &count;
8700         r2.out.info     = &info;
8701         r2.out.needed   = &needed;
8702
8703         result = _spoolss_EnumPrinterDataEx(p, &r2);
8704         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8705                 r2.in.offered = needed;
8706                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8707         }
8708         if (!W_ERROR_IS_OK(result)) {
8709                 return result;
8710         }
8711
8712         /*
8713          * The NT machine wants to know the biggest size of value and data
8714          *
8715          * cf: MSDN EnumPrinterData remark section
8716          */
8717
8718         if (!r->in.value_offered && !r->in.data_offered) {
8719                 uint32_t biggest_valuesize = 0;
8720                 uint32_t biggest_datasize = 0;
8721                 int i, name_length;
8722
8723                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8724
8725                 for (i=0; i<count; i++) {
8726
8727                         name_length = strlen(info[i].value_name);
8728                         if (strlen(info[i].value_name) > biggest_valuesize) {
8729                                 biggest_valuesize = name_length;
8730                         }
8731
8732                         if (info[i].data_length > biggest_datasize) {
8733                                 biggest_datasize = info[i].data_length;
8734                         }
8735
8736                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8737                                 biggest_datasize));
8738                 }
8739
8740                 /* the value is an UNICODE string but real_value_size is the length
8741                    in bytes including the trailing 0 */
8742
8743                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8744                 *r->out.data_needed  = biggest_datasize;
8745
8746                 DEBUG(6,("final values: [%d], [%d]\n",
8747                         *r->out.value_needed, *r->out.data_needed));
8748
8749                 return WERR_OK;
8750         }
8751
8752         if (r->in.enum_index < count) {
8753                 val = &info[r->in.enum_index];
8754         }
8755
8756         if (val == NULL) {
8757                 /* out_value should default to "" or else NT4 has
8758                    problems unmarshalling the response */
8759
8760                 if (r->in.value_offered) {
8761                         *r->out.value_needed = 1;
8762                         r->out.value_name = talloc_strdup(r, "");
8763                         if (!r->out.value_name) {
8764                                 return WERR_NOMEM;
8765                         }
8766                 } else {
8767                         r->out.value_name = NULL;
8768                         *r->out.value_needed = 0;
8769                 }
8770
8771                 /* the data is counted in bytes */
8772
8773                 *r->out.data_needed = r->in.data_offered;
8774
8775                 result = WERR_NO_MORE_ITEMS;
8776         } else {
8777                 /*
8778                  * the value is:
8779                  * - counted in bytes in the request
8780                  * - counted in UNICODE chars in the max reply
8781                  * - counted in bytes in the real size
8782                  *
8783                  * take a pause *before* coding not *during* coding
8784                  */
8785
8786                 /* name */
8787                 if (r->in.value_offered) {
8788                         r->out.value_name = talloc_strdup(r, val->value_name);
8789                         if (!r->out.value_name) {
8790                                 return WERR_NOMEM;
8791                         }
8792                         *r->out.value_needed = val->value_name_len;
8793                 } else {
8794                         r->out.value_name = NULL;
8795                         *r->out.value_needed = 0;
8796                 }
8797
8798                 /* type */
8799
8800                 *r->out.type = val->type;
8801
8802                 /* data - counted in bytes */
8803
8804                 /*
8805                  * See the section "Dynamically Typed Query Parameters"
8806                  * in MS-RPRN.
8807                  */
8808
8809                 if (r->out.data && val->data && val->data->data &&
8810                                 val->data_length && r->in.data_offered) {
8811                         memcpy(r->out.data, val->data->data,
8812                                 MIN(val->data_length,r->in.data_offered));
8813                 }
8814
8815                 *r->out.data_needed = val->data_length;
8816
8817                 result = WERR_OK;
8818         }
8819
8820         return result;
8821 }
8822
8823 /****************************************************************
8824  _spoolss_SetPrinterData
8825 ****************************************************************/
8826
8827 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8828                                struct spoolss_SetPrinterData *r)
8829 {
8830         struct spoolss_SetPrinterDataEx r2;
8831
8832         r2.in.handle            = r->in.handle;
8833         r2.in.key_name          = "PrinterDriverData";
8834         r2.in.value_name        = r->in.value_name;
8835         r2.in.type              = r->in.type;
8836         r2.in.data              = r->in.data;
8837         r2.in.offered           = r->in.offered;
8838
8839         return _spoolss_SetPrinterDataEx(p, &r2);
8840 }
8841
8842 /****************************************************************
8843  _spoolss_ResetPrinter
8844 ****************************************************************/
8845
8846 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8847                              struct spoolss_ResetPrinter *r)
8848 {
8849         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8850         int             snum;
8851
8852         DEBUG(5,("_spoolss_ResetPrinter\n"));
8853
8854         /*
8855          * All we do is to check to see if the handle and queue is valid.
8856          * This call really doesn't mean anything to us because we only
8857          * support RAW printing.   --jerry
8858          */
8859
8860         if (!Printer) {
8861                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8862                         OUR_HANDLE(r->in.handle)));
8863                 return WERR_BADFID;
8864         }
8865
8866         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8867                 return WERR_BADFID;
8868
8869
8870         /* blindly return success */
8871         return WERR_OK;
8872 }
8873
8874 /****************************************************************
8875  _spoolss_DeletePrinterData
8876 ****************************************************************/
8877
8878 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8879                                   struct spoolss_DeletePrinterData *r)
8880 {
8881         struct spoolss_DeletePrinterDataEx r2;
8882
8883         r2.in.handle            = r->in.handle;
8884         r2.in.key_name          = "PrinterDriverData";
8885         r2.in.value_name        = r->in.value_name;
8886
8887         return _spoolss_DeletePrinterDataEx(p, &r2);
8888 }
8889
8890 /****************************************************************
8891  _spoolss_AddForm
8892 ****************************************************************/
8893
8894 WERROR _spoolss_AddForm(struct pipes_struct *p,
8895                         struct spoolss_AddForm *r)
8896 {
8897         struct spoolss_AddFormInfo1 *form;
8898         int snum = -1;
8899         WERROR status = WERR_OK;
8900         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8901         struct dcerpc_binding_handle *b;
8902         TALLOC_CTX *tmp_ctx = NULL;
8903
8904         DEBUG(5,("_spoolss_AddForm\n"));
8905
8906         if (!Printer) {
8907                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8908                         OUR_HANDLE(r->in.handle)));
8909                 return WERR_BADFID;
8910         }
8911
8912         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8913            and not a printer admin, then fail */
8914
8915         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8916             !security_token_has_privilege(p->session_info->security_token,
8917                                           SEC_PRIV_PRINT_OPERATOR)) {
8918                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8919                 return WERR_ACCESS_DENIED;
8920         }
8921
8922         if (r->in.info_ctr->level != 1) {
8923                 return WERR_INVALID_LEVEL;
8924         }
8925
8926         form = r->in.info_ctr->info.info1;
8927         if (!form) {
8928                 return WERR_INVALID_PARAM;
8929         }
8930
8931         switch (form->flags) {
8932         case SPOOLSS_FORM_USER:
8933         case SPOOLSS_FORM_BUILTIN:
8934         case SPOOLSS_FORM_PRINTER:
8935                 break;
8936         default:
8937                 return WERR_INVALID_PARAM;
8938         }
8939
8940         tmp_ctx = talloc_new(p->mem_ctx);
8941         if (!tmp_ctx) {
8942                 return WERR_NOMEM;
8943         }
8944
8945         status = winreg_printer_binding_handle(tmp_ctx,
8946                                                get_session_info_system(),
8947                                                p->msg_ctx,
8948                                                &b);
8949         if (!W_ERROR_IS_OK(status)) {
8950                 goto done;
8951         }
8952
8953         status = winreg_printer_addform1(tmp_ctx, b, form);
8954         if (!W_ERROR_IS_OK(status)) {
8955                 goto done;
8956         }
8957
8958         /*
8959          * ChangeID must always be set if this is a printer
8960          */
8961         if (Printer->printer_type == SPLHND_PRINTER) {
8962                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8963                         status = WERR_BADFID;
8964                         goto done;
8965                 }
8966
8967                 status = winreg_printer_update_changeid(tmp_ctx, b,
8968                                                         lp_const_servicename(snum));
8969         }
8970
8971 done:
8972         talloc_free(tmp_ctx);
8973         return status;
8974 }
8975
8976 /****************************************************************
8977  _spoolss_DeleteForm
8978 ****************************************************************/
8979
8980 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8981                            struct spoolss_DeleteForm *r)
8982 {
8983         const char *form_name = r->in.form_name;
8984         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8985         int snum = -1;
8986         WERROR status = WERR_OK;
8987         struct dcerpc_binding_handle *b;
8988         TALLOC_CTX *tmp_ctx = NULL;
8989
8990         DEBUG(5,("_spoolss_DeleteForm\n"));
8991
8992         if (!Printer) {
8993                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8994                         OUR_HANDLE(r->in.handle)));
8995                 return WERR_BADFID;
8996         }
8997
8998         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8999             !security_token_has_privilege(p->session_info->security_token,
9000                                           SEC_PRIV_PRINT_OPERATOR)) {
9001                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9002                 return WERR_ACCESS_DENIED;
9003         }
9004
9005         tmp_ctx = talloc_new(p->mem_ctx);
9006         if (!tmp_ctx) {
9007                 return WERR_NOMEM;
9008         }
9009
9010         status = winreg_printer_binding_handle(tmp_ctx,
9011                                                get_session_info_system(),
9012                                                p->msg_ctx,
9013                                                &b);
9014         if (!W_ERROR_IS_OK(status)) {
9015                 goto done;
9016         }
9017
9018         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9019         if (!W_ERROR_IS_OK(status)) {
9020                 goto done;
9021         }
9022
9023         /*
9024          * ChangeID must always be set if this is a printer
9025          */
9026         if (Printer->printer_type == SPLHND_PRINTER) {
9027                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9028                         status = WERR_BADFID;
9029                         goto done;
9030                 }
9031
9032                 status = winreg_printer_update_changeid(tmp_ctx, b,
9033                                                         lp_const_servicename(snum));
9034         }
9035
9036 done:
9037         talloc_free(tmp_ctx);
9038         return status;
9039 }
9040
9041 /****************************************************************
9042  _spoolss_SetForm
9043 ****************************************************************/
9044
9045 WERROR _spoolss_SetForm(struct pipes_struct *p,
9046                         struct spoolss_SetForm *r)
9047 {
9048         struct spoolss_AddFormInfo1 *form;
9049         const char *form_name = r->in.form_name;
9050         int snum = -1;
9051         WERROR status = WERR_OK;
9052         struct dcerpc_binding_handle *b;
9053         TALLOC_CTX *tmp_ctx = NULL;
9054
9055         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9056
9057         DEBUG(5,("_spoolss_SetForm\n"));
9058
9059         if (!Printer) {
9060                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9061                         OUR_HANDLE(r->in.handle)));
9062                 return WERR_BADFID;
9063         }
9064
9065         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9066            and not a printer admin, then fail */
9067
9068         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9069              !security_token_has_privilege(p->session_info->security_token,
9070                                            SEC_PRIV_PRINT_OPERATOR)) {
9071                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
9072                 return WERR_ACCESS_DENIED;
9073         }
9074
9075         if (r->in.info_ctr->level != 1) {
9076                 return WERR_INVALID_LEVEL;
9077         }
9078
9079         form = r->in.info_ctr->info.info1;
9080         if (!form) {
9081                 return WERR_INVALID_PARAM;
9082         }
9083
9084         tmp_ctx = talloc_new(p->mem_ctx);
9085         if (!tmp_ctx) {
9086                 return WERR_NOMEM;
9087         }
9088
9089         status = winreg_printer_binding_handle(tmp_ctx,
9090                                                get_session_info_system(),
9091                                                p->msg_ctx,
9092                                                &b);
9093         if (!W_ERROR_IS_OK(status)) {
9094                 goto done;
9095         }
9096
9097         status = winreg_printer_setform1(tmp_ctx, b,
9098                                          form_name,
9099                                          form);
9100         if (!W_ERROR_IS_OK(status)) {
9101                 goto done;
9102         }
9103
9104         /*
9105          * ChangeID must always be set if this is a printer
9106          */
9107         if (Printer->printer_type == SPLHND_PRINTER) {
9108                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9109                         status = WERR_BADFID;
9110                         goto done;
9111                 }
9112
9113                 status = winreg_printer_update_changeid(tmp_ctx, b,
9114                                                         lp_const_servicename(snum));
9115         }
9116
9117 done:
9118         talloc_free(tmp_ctx);
9119         return status;
9120 }
9121
9122 /****************************************************************************
9123  fill_print_processor1
9124 ****************************************************************************/
9125
9126 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9127                                     struct spoolss_PrintProcessorInfo1 *r,
9128                                     const char *print_processor_name)
9129 {
9130         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9131         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9132
9133         return WERR_OK;
9134 }
9135
9136 /****************************************************************************
9137  enumprintprocessors level 1.
9138 ****************************************************************************/
9139
9140 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9141                                           union spoolss_PrintProcessorInfo **info_p,
9142                                           uint32_t *count)
9143 {
9144         union spoolss_PrintProcessorInfo *info;
9145         WERROR result;
9146
9147         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9148         W_ERROR_HAVE_NO_MEMORY(info);
9149
9150         *count = 1;
9151
9152         result = fill_print_processor1(info, &info[0].info1, "winprint");
9153         if (!W_ERROR_IS_OK(result)) {
9154                 goto out;
9155         }
9156
9157  out:
9158         if (!W_ERROR_IS_OK(result)) {
9159                 TALLOC_FREE(info);
9160                 *count = 0;
9161                 return result;
9162         }
9163
9164         *info_p = info;
9165
9166         return WERR_OK;
9167 }
9168
9169 /****************************************************************
9170  _spoolss_EnumPrintProcessors
9171 ****************************************************************/
9172
9173 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9174                                     struct spoolss_EnumPrintProcessors *r)
9175 {
9176         WERROR result;
9177
9178         /* that's an [in out] buffer */
9179
9180         if (!r->in.buffer && (r->in.offered != 0)) {
9181                 return WERR_INVALID_PARAM;
9182         }
9183
9184         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9185
9186         /*
9187          * Enumerate the print processors ...
9188          *
9189          * Just reply with "winprint", to keep NT happy
9190          * and I can use my nice printer checker.
9191          */
9192
9193         *r->out.count = 0;
9194         *r->out.needed = 0;
9195         *r->out.info = NULL;
9196
9197         if (!get_short_archi(r->in.environment)) {
9198                 return WERR_INVALID_ENVIRONMENT;
9199         }
9200
9201         switch (r->in.level) {
9202         case 1:
9203                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9204                                                      r->out.count);
9205                 break;
9206         default:
9207                 return WERR_UNKNOWN_LEVEL;
9208         }
9209
9210         if (!W_ERROR_IS_OK(result)) {
9211                 return result;
9212         }
9213
9214         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9215                                                      spoolss_EnumPrintProcessors,
9216                                                      *r->out.info, r->in.level,
9217                                                      *r->out.count);
9218         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9219         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9220
9221         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9222 }
9223
9224 /****************************************************************************
9225  fill_printprocdatatype1
9226 ****************************************************************************/
9227
9228 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9229                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9230                                       const char *name_array)
9231 {
9232         r->name_array = talloc_strdup(mem_ctx, name_array);
9233         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9234
9235         return WERR_OK;
9236 }
9237
9238 /****************************************************************************
9239  enumprintprocdatatypes level 1.
9240 ****************************************************************************/
9241
9242 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9243                                              union spoolss_PrintProcDataTypesInfo **info_p,
9244                                              uint32_t *count)
9245 {
9246         WERROR result;
9247         union spoolss_PrintProcDataTypesInfo *info;
9248
9249         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9250         W_ERROR_HAVE_NO_MEMORY(info);
9251
9252         *count = 1;
9253
9254         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9255         if (!W_ERROR_IS_OK(result)) {
9256                 goto out;
9257         }
9258
9259  out:
9260         if (!W_ERROR_IS_OK(result)) {
9261                 TALLOC_FREE(info);
9262                 *count = 0;
9263                 return result;
9264         }
9265
9266         *info_p = info;
9267
9268         return WERR_OK;
9269 }
9270
9271 /****************************************************************
9272  _spoolss_EnumPrintProcDataTypes
9273 ****************************************************************/
9274
9275 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9276                                        struct spoolss_EnumPrintProcDataTypes *r)
9277 {
9278         WERROR result;
9279
9280         /* that's an [in out] buffer */
9281
9282         if (!r->in.buffer && (r->in.offered != 0)) {
9283                 return WERR_INVALID_PARAM;
9284         }
9285
9286         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9287
9288         *r->out.count = 0;
9289         *r->out.needed = 0;
9290         *r->out.info = NULL;
9291
9292         if (r->in.print_processor_name == NULL ||
9293             !strequal(r->in.print_processor_name, "winprint")) {
9294                 return WERR_UNKNOWN_PRINTPROCESSOR;
9295         }
9296
9297         switch (r->in.level) {
9298         case 1:
9299                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9300                                                         r->out.count);
9301                 break;
9302         default:
9303                 return WERR_UNKNOWN_LEVEL;
9304         }
9305
9306         if (!W_ERROR_IS_OK(result)) {
9307                 return result;
9308         }
9309
9310         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9311                                                      spoolss_EnumPrintProcDataTypes,
9312                                                      *r->out.info, r->in.level,
9313                                                      *r->out.count);
9314         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9315         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9316
9317         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9318 }
9319
9320 /****************************************************************************
9321  fill_monitor_1
9322 ****************************************************************************/
9323
9324 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9325                              struct spoolss_MonitorInfo1 *r,
9326                              const char *monitor_name)
9327 {
9328         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9329         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9330
9331         return WERR_OK;
9332 }
9333
9334 /****************************************************************************
9335  fill_monitor_2
9336 ****************************************************************************/
9337
9338 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9339                              struct spoolss_MonitorInfo2 *r,
9340                              const char *monitor_name,
9341                              const char *environment,
9342                              const char *dll_name)
9343 {
9344         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9345         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9346         r->environment                  = talloc_strdup(mem_ctx, environment);
9347         W_ERROR_HAVE_NO_MEMORY(r->environment);
9348         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9349         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9350
9351         return WERR_OK;
9352 }
9353
9354 /****************************************************************************
9355  enumprintmonitors level 1.
9356 ****************************************************************************/
9357
9358 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9359                                         union spoolss_MonitorInfo **info_p,
9360                                         uint32_t *count)
9361 {
9362         union spoolss_MonitorInfo *info;
9363         WERROR result = WERR_OK;
9364
9365         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9366         W_ERROR_HAVE_NO_MEMORY(info);
9367
9368         *count = 2;
9369
9370         result = fill_monitor_1(info, &info[0].info1,
9371                                 SPL_LOCAL_PORT);
9372         if (!W_ERROR_IS_OK(result)) {
9373                 goto out;
9374         }
9375
9376         result = fill_monitor_1(info, &info[1].info1,
9377                                 SPL_TCPIP_PORT);
9378         if (!W_ERROR_IS_OK(result)) {
9379                 goto out;
9380         }
9381
9382 out:
9383         if (!W_ERROR_IS_OK(result)) {
9384                 TALLOC_FREE(info);
9385                 *count = 0;
9386                 return result;
9387         }
9388
9389         *info_p = info;
9390
9391         return WERR_OK;
9392 }
9393
9394 /****************************************************************************
9395  enumprintmonitors level 2.
9396 ****************************************************************************/
9397
9398 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9399                                         union spoolss_MonitorInfo **info_p,
9400                                         uint32_t *count)
9401 {
9402         union spoolss_MonitorInfo *info;
9403         WERROR result = WERR_OK;
9404
9405         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9406         W_ERROR_HAVE_NO_MEMORY(info);
9407
9408         *count = 2;
9409
9410         result = fill_monitor_2(info, &info[0].info2,
9411                                 SPL_LOCAL_PORT,
9412                                 "Windows NT X86", /* FIXME */
9413                                 "localmon.dll");
9414         if (!W_ERROR_IS_OK(result)) {
9415                 goto out;
9416         }
9417
9418         result = fill_monitor_2(info, &info[1].info2,
9419                                 SPL_TCPIP_PORT,
9420                                 "Windows NT X86", /* FIXME */
9421                                 "tcpmon.dll");
9422         if (!W_ERROR_IS_OK(result)) {
9423                 goto out;
9424         }
9425
9426 out:
9427         if (!W_ERROR_IS_OK(result)) {
9428                 TALLOC_FREE(info);
9429                 *count = 0;
9430                 return result;
9431         }
9432
9433         *info_p = info;
9434
9435         return WERR_OK;
9436 }
9437
9438 /****************************************************************
9439  _spoolss_EnumMonitors
9440 ****************************************************************/
9441
9442 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9443                              struct spoolss_EnumMonitors *r)
9444 {
9445         WERROR result;
9446
9447         /* that's an [in out] buffer */
9448
9449         if (!r->in.buffer && (r->in.offered != 0)) {
9450                 return WERR_INVALID_PARAM;
9451         }
9452
9453         DEBUG(5,("_spoolss_EnumMonitors\n"));
9454
9455         /*
9456          * Enumerate the print monitors ...
9457          *
9458          * Just reply with "Local Port", to keep NT happy
9459          * and I can use my nice printer checker.
9460          */
9461
9462         *r->out.count = 0;
9463         *r->out.needed = 0;
9464         *r->out.info = NULL;
9465
9466         switch (r->in.level) {
9467         case 1:
9468                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9469                                                    r->out.count);
9470                 break;
9471         case 2:
9472                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9473                                                    r->out.count);
9474                 break;
9475         default:
9476                 return WERR_UNKNOWN_LEVEL;
9477         }
9478
9479         if (!W_ERROR_IS_OK(result)) {
9480                 return result;
9481         }
9482
9483         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9484                                                      spoolss_EnumMonitors,
9485                                                      *r->out.info, r->in.level,
9486                                                      *r->out.count);
9487         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9488         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9489
9490         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9491 }
9492
9493 /****************************************************************************
9494 ****************************************************************************/
9495
9496 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9497                              const print_queue_struct *queue,
9498                              int count, int snum,
9499                              struct spoolss_PrinterInfo2 *pinfo2,
9500                              uint32_t jobid,
9501                              int sysjob,
9502                              struct spoolss_JobInfo1 *r)
9503 {
9504         int i = 0;
9505         bool found = false;
9506
9507         for (i=0; i<count; i++) {
9508                 if (queue[i].sysjob == sysjob) {
9509                         found = true;
9510                         break;
9511                 }
9512         }
9513
9514         if (found == false) {
9515                 /* NT treats not found as bad param... yet another bad choice */
9516                 return WERR_INVALID_PARAM;
9517         }
9518
9519         return fill_job_info1(mem_ctx,
9520                               r,
9521                               &queue[i],
9522                               jobid,
9523                               i,
9524                               snum,
9525                               pinfo2);
9526 }
9527
9528 /****************************************************************************
9529 ****************************************************************************/
9530
9531 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9532                              const print_queue_struct *queue,
9533                              int count, int snum,
9534                              struct spoolss_PrinterInfo2 *pinfo2,
9535                              uint32_t jobid,
9536                              int sysjob,
9537                              struct spoolss_JobInfo2 *r)
9538 {
9539         int i = 0;
9540         bool found = false;
9541         struct spoolss_DeviceMode *devmode;
9542         WERROR result;
9543
9544         for (i=0; i<count; i++) {
9545                 if (queue[i].sysjob == sysjob) {
9546                         found = true;
9547                         break;
9548                 }
9549         }
9550
9551         if (found == false) {
9552                 /* NT treats not found as bad param... yet another bad
9553                    choice */
9554                 return WERR_INVALID_PARAM;
9555         }
9556
9557         /*
9558          * if the print job does not have a DEVMODE associated with it,
9559          * just use the one for the printer. A NULL devicemode is not
9560          *  a failure condition
9561          */
9562
9563         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9564         if (!devmode) {
9565                 result = spoolss_create_default_devmode(mem_ctx,
9566                                                 pinfo2->printername,
9567                                                 &devmode);
9568                 if (!W_ERROR_IS_OK(result)) {
9569                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9570                         return result;
9571                 }
9572         }
9573
9574         return fill_job_info2(mem_ctx,
9575                               r,
9576                               &queue[i],
9577                               jobid,
9578                               i,
9579                               snum,
9580                               pinfo2,
9581                               devmode);
9582 }
9583
9584 /****************************************************************
9585  _spoolss_GetJob
9586 ****************************************************************/
9587
9588 WERROR _spoolss_GetJob(struct pipes_struct *p,
9589                        struct spoolss_GetJob *r)
9590 {
9591         WERROR result = WERR_OK;
9592         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9593         const char *svc_name;
9594         int sysjob;
9595         int snum;
9596         int count;
9597         struct tdb_print_db *pdb;
9598         print_queue_struct      *queue = NULL;
9599         print_status_struct prt_status;
9600
9601         /* that's an [in out] buffer */
9602
9603         if (!r->in.buffer && (r->in.offered != 0)) {
9604                 result = WERR_INVALID_PARAM;
9605                 goto err_jinfo_free;
9606         }
9607
9608         DEBUG(5,("_spoolss_GetJob\n"));
9609
9610         *r->out.needed = 0;
9611
9612         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9613                 result = WERR_BADFID;
9614                 goto err_jinfo_free;
9615         }
9616
9617         svc_name = lp_const_servicename(snum);
9618         if (svc_name == NULL) {
9619                 result = WERR_INVALID_PARAM;
9620                 goto err_jinfo_free;
9621         }
9622
9623         result = winreg_get_printer_internal(p->mem_ctx,
9624                                     get_session_info_system(),
9625                                     p->msg_ctx,
9626                                     svc_name,
9627                                     &pinfo2);
9628         if (!W_ERROR_IS_OK(result)) {
9629                 goto err_jinfo_free;
9630         }
9631
9632         pdb = get_print_db_byname(svc_name);
9633         if (pdb == NULL) {
9634                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9635                 result = WERR_INVALID_PARAM;
9636                 goto err_pinfo_free;
9637         }
9638
9639         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9640         release_print_db(pdb);
9641         if (sysjob == -1) {
9642                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9643                 result = WERR_INVALID_PARAM;
9644                 goto err_pinfo_free;
9645         }
9646
9647         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9648
9649         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9650                      count, prt_status.status, prt_status.message));
9651
9652         switch (r->in.level) {
9653         case 1:
9654                 result = getjob_level_1(p->mem_ctx,
9655                                         queue, count, snum, pinfo2,
9656                                         r->in.job_id, sysjob,
9657                                         &r->out.info->info1);
9658                 break;
9659         case 2:
9660                 result = getjob_level_2(p->mem_ctx,
9661                                         queue, count, snum, pinfo2,
9662                                         r->in.job_id, sysjob,
9663                                         &r->out.info->info2);
9664                 break;
9665         default:
9666                 result = WERR_UNKNOWN_LEVEL;
9667                 break;
9668         }
9669
9670         SAFE_FREE(queue);
9671         TALLOC_FREE(pinfo2);
9672
9673         if (!W_ERROR_IS_OK(result)) {
9674                 goto err_jinfo_free;
9675         }
9676
9677         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9678                                                                                    r->in.level);
9679         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9680
9681         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9682
9683 err_pinfo_free:
9684         TALLOC_FREE(pinfo2);
9685 err_jinfo_free:
9686         TALLOC_FREE(r->out.info);
9687         return result;
9688 }
9689
9690 /****************************************************************
9691  _spoolss_GetPrinterDataEx
9692 ****************************************************************/
9693
9694 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9695                                  struct spoolss_GetPrinterDataEx *r)
9696 {
9697
9698         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9699         const char *printer;
9700         int                     snum = 0;
9701         WERROR result = WERR_OK;
9702         DATA_BLOB blob;
9703         enum winreg_Type val_type = REG_NONE;
9704         uint8_t *val_data = NULL;
9705         uint32_t val_size = 0;
9706         struct dcerpc_binding_handle *b;
9707         TALLOC_CTX *tmp_ctx;
9708
9709         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9710
9711         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9712                 r->in.key_name, r->in.value_name));
9713
9714         /* in case of problem, return some default values */
9715
9716         *r->out.needed  = 0;
9717         *r->out.type    = REG_NONE;
9718
9719         tmp_ctx = talloc_new(p->mem_ctx);
9720         if (!tmp_ctx) {
9721                 return WERR_NOMEM;
9722         }
9723
9724         if (!Printer) {
9725                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9726                         OUR_HANDLE(r->in.handle)));
9727                 result = WERR_BADFID;
9728                 goto done;
9729         }
9730
9731         /* Is the handle to a printer or to the server? */
9732
9733         if (Printer->printer_type == SPLHND_SERVER) {
9734
9735                 union spoolss_PrinterData data;
9736
9737                 result = getprinterdata_printer_server(tmp_ctx,
9738                                                        r->in.value_name,
9739                                                        r->out.type,
9740                                                        &data);
9741                 if (!W_ERROR_IS_OK(result)) {
9742                         goto done;
9743                 }
9744
9745                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9746                                                   *r->out.type, &data);
9747                 if (!W_ERROR_IS_OK(result)) {
9748                         goto done;
9749                 }
9750
9751                 *r->out.needed = blob.length;
9752
9753                 if (r->in.offered >= *r->out.needed) {
9754                         memcpy(r->out.data, blob.data, blob.length);
9755                 }
9756
9757                 result = WERR_OK;
9758                 goto done;
9759         }
9760
9761         /* check to see if the keyname is valid */
9762         if (!strlen(r->in.key_name)) {
9763                 result = WERR_INVALID_PARAM;
9764                 goto done;
9765         }
9766
9767         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9768                 result = WERR_BADFID;
9769                 goto done;
9770         }
9771         printer = lp_const_servicename(snum);
9772
9773         result = winreg_printer_binding_handle(tmp_ctx,
9774                                                get_session_info_system(),
9775                                                p->msg_ctx,
9776                                                &b);
9777         if (!W_ERROR_IS_OK(result)) {
9778                 goto done;
9779         }
9780
9781         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9782         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9783             strequal(r->in.value_name, "ChangeId")) {
9784                 *r->out.type = REG_DWORD;
9785                 *r->out.needed = 4;
9786                 if (r->in.offered >= *r->out.needed) {
9787                         uint32_t changeid = 0;
9788
9789                         result = winreg_printer_get_changeid(tmp_ctx, b,
9790                                                              printer,
9791                                                              &changeid);
9792                         if (!W_ERROR_IS_OK(result)) {
9793                                 goto done;
9794                         }
9795
9796                         SIVAL(r->out.data, 0, changeid);
9797                         result = WERR_OK;
9798                 }
9799                 goto done;
9800         }
9801
9802         result = winreg_get_printer_dataex(tmp_ctx, b,
9803                                            printer,
9804                                            r->in.key_name,
9805                                            r->in.value_name,
9806                                            &val_type,
9807                                            &val_data,
9808                                            &val_size);
9809         if (!W_ERROR_IS_OK(result)) {
9810                 goto done;
9811         }
9812
9813         *r->out.needed = val_size;
9814         *r->out.type = val_type;
9815
9816         if (r->in.offered >= *r->out.needed) {
9817                 memcpy(r->out.data, val_data, val_size);
9818         }
9819
9820 done:
9821         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9822
9823         if (W_ERROR_IS_OK(result)) {
9824                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9825         }
9826
9827         talloc_free(tmp_ctx);
9828         return result;
9829 }
9830
9831 /****************************************************************
9832  _spoolss_SetPrinterDataEx
9833 ****************************************************************/
9834
9835 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9836                                  struct spoolss_SetPrinterDataEx *r)
9837 {
9838         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9839         int                     snum = 0;
9840         WERROR                  result = WERR_OK;
9841         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9842         char                    *oid_string;
9843         struct dcerpc_binding_handle *b;
9844         TALLOC_CTX *tmp_ctx;
9845
9846         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9847
9848         /* From MSDN documentation of SetPrinterDataEx: pass request to
9849            SetPrinterData if key is "PrinterDriverData" */
9850
9851         if (!Printer) {
9852                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9853                         OUR_HANDLE(r->in.handle)));
9854                 return WERR_BADFID;
9855         }
9856
9857         if (Printer->printer_type == SPLHND_SERVER) {
9858                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9859                         "Not implemented for server handles yet\n"));
9860                 return WERR_INVALID_PARAM;
9861         }
9862
9863         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9864                 return WERR_BADFID;
9865         }
9866
9867         /*
9868          * Access check : NT returns "access denied" if you make a
9869          * SetPrinterData call without the necessary privildge.
9870          * we were originally returning OK if nothing changed
9871          * which made Win2k issue **a lot** of SetPrinterData
9872          * when connecting to a printer  --jerry
9873          */
9874
9875         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9876                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9877                         "change denied by handle access permissions\n"));
9878                 return WERR_ACCESS_DENIED;
9879         }
9880
9881         tmp_ctx = talloc_new(p->mem_ctx);
9882         if (!tmp_ctx) {
9883                 return WERR_NOMEM;
9884         }
9885
9886         result = winreg_printer_binding_handle(tmp_ctx,
9887                                                get_session_info_system(),
9888                                                p->msg_ctx,
9889                                                &b);
9890         if (!W_ERROR_IS_OK(result)) {
9891                 goto done;
9892         }
9893
9894         result = winreg_get_printer(tmp_ctx, b,
9895                                     lp_servicename(talloc_tos(), snum),
9896                                     &pinfo2);
9897         if (!W_ERROR_IS_OK(result)) {
9898                 goto done;
9899         }
9900
9901         /* check for OID in valuename */
9902
9903         oid_string = strchr(r->in.value_name, ',');
9904         if (oid_string) {
9905                 *oid_string = '\0';
9906                 oid_string++;
9907         }
9908
9909         /* save the registry data */
9910
9911         result = winreg_set_printer_dataex(tmp_ctx, b,
9912                                            pinfo2->sharename,
9913                                            r->in.key_name,
9914                                            r->in.value_name,
9915                                            r->in.type,
9916                                            r->in.data,
9917                                            r->in.offered);
9918
9919         if (W_ERROR_IS_OK(result)) {
9920                 /* save the OID if one was specified */
9921                 if (oid_string) {
9922                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9923                                 r->in.key_name, SPOOL_OID_KEY);
9924                         if (!str) {
9925                                 result = WERR_NOMEM;
9926                                 goto done;
9927                         }
9928
9929                         /*
9930                          * I'm not checking the status here on purpose.  Don't know
9931                          * if this is right, but I'm returning the status from the
9932                          * previous set_printer_dataex() call.  I have no idea if
9933                          * this is right.    --jerry
9934                          */
9935                         winreg_set_printer_dataex(tmp_ctx, b,
9936                                                   pinfo2->sharename,
9937                                                   str,
9938                                                   r->in.value_name,
9939                                                   REG_SZ,
9940                                                   (uint8_t *) oid_string,
9941                                                   strlen(oid_string) + 1);
9942                 }
9943
9944                 result = winreg_printer_update_changeid(tmp_ctx, b,
9945                                                         lp_const_servicename(snum));
9946
9947         }
9948
9949 done:
9950         talloc_free(tmp_ctx);
9951         return result;
9952 }
9953
9954 /****************************************************************
9955  _spoolss_DeletePrinterDataEx
9956 ****************************************************************/
9957
9958 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9959                                     struct spoolss_DeletePrinterDataEx *r)
9960 {
9961         const char *printer;
9962         int             snum=0;
9963         WERROR          status = WERR_OK;
9964         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9965
9966         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9967
9968         if (!Printer) {
9969                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9970                         "Invalid handle (%s:%u:%u).\n",
9971                         OUR_HANDLE(r->in.handle)));
9972                 return WERR_BADFID;
9973         }
9974
9975         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9976                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9977                         "printer properties change denied by handle\n"));
9978                 return WERR_ACCESS_DENIED;
9979         }
9980
9981         if (!r->in.value_name || !r->in.key_name) {
9982                 return WERR_NOMEM;
9983         }
9984
9985         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9986                 return WERR_BADFID;
9987         }
9988         printer = lp_const_servicename(snum);
9989
9990         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9991                                               get_session_info_system(),
9992                                               p->msg_ctx,
9993                                               printer,
9994                                               r->in.key_name,
9995                                               r->in.value_name);
9996         if (W_ERROR_IS_OK(status)) {
9997                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9998                                                         get_session_info_system(),
9999                                                         p->msg_ctx,
10000                                                         printer);
10001         }
10002
10003         return status;
10004 }
10005
10006 /****************************************************************
10007  _spoolss_EnumPrinterKey
10008 ****************************************************************/
10009
10010 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10011                                struct spoolss_EnumPrinterKey *r)
10012 {
10013         uint32_t        num_keys;
10014         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10015         int             snum = 0;
10016         WERROR          result = WERR_BADFILE;
10017         const char **array = NULL;
10018         DATA_BLOB blob;
10019
10020         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10021
10022         if (!Printer) {
10023                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10024                         OUR_HANDLE(r->in.handle)));
10025                 return WERR_BADFID;
10026         }
10027
10028         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10029                 return WERR_BADFID;
10030         }
10031
10032         result = winreg_enum_printer_key_internal(p->mem_ctx,
10033                                          get_session_info_system(),
10034                                          p->msg_ctx,
10035                                          lp_const_servicename(snum),
10036                                          r->in.key_name,
10037                                          &num_keys,
10038                                          &array);
10039         if (!W_ERROR_IS_OK(result)) {
10040                 goto done;
10041         }
10042
10043         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10044                 result = WERR_NOMEM;
10045                 goto done;
10046         }
10047
10048         *r->out._ndr_size = r->in.offered / 2;
10049         *r->out.needed = blob.length;
10050
10051         if (r->in.offered < *r->out.needed) {
10052                 result = WERR_MORE_DATA;
10053         } else {
10054                 result = WERR_OK;
10055                 r->out.key_buffer->string_array = array;
10056         }
10057
10058  done:
10059         if (!W_ERROR_IS_OK(result)) {
10060                 TALLOC_FREE(array);
10061                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10062                         *r->out.needed = 0;
10063                 }
10064         }
10065
10066         return result;
10067 }
10068
10069 /****************************************************************
10070  _spoolss_DeletePrinterKey
10071 ****************************************************************/
10072
10073 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10074                                  struct spoolss_DeletePrinterKey *r)
10075 {
10076         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10077         int                     snum=0;
10078         WERROR                  status;
10079         const char *printer;
10080         struct dcerpc_binding_handle *b;
10081         TALLOC_CTX *tmp_ctx;
10082
10083         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10084
10085         if (!Printer) {
10086                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10087                         OUR_HANDLE(r->in.handle)));
10088                 return WERR_BADFID;
10089         }
10090
10091         /* if keyname == NULL, return error */
10092         if ( !r->in.key_name )
10093                 return WERR_INVALID_PARAM;
10094
10095         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10096                 return WERR_BADFID;
10097         }
10098
10099         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10100                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10101                         "printer properties change denied by handle\n"));
10102                 return WERR_ACCESS_DENIED;
10103         }
10104
10105         printer = lp_const_servicename(snum);
10106
10107         tmp_ctx = talloc_new(p->mem_ctx);
10108         if (!tmp_ctx) {
10109                 return WERR_NOMEM;
10110         }
10111
10112         status = winreg_printer_binding_handle(tmp_ctx,
10113                                                get_session_info_system(),
10114                                                p->msg_ctx,
10115                                                &b);
10116         if (!W_ERROR_IS_OK(status)) {
10117                 goto done;
10118         }
10119
10120         /* delete the key and all subkeys */
10121         status = winreg_delete_printer_key(tmp_ctx, b,
10122                                            printer,
10123                                            r->in.key_name);
10124         if (W_ERROR_IS_OK(status)) {
10125                 status = winreg_printer_update_changeid(tmp_ctx, b,
10126                                                         printer);
10127         }
10128
10129 done:
10130         talloc_free(tmp_ctx);
10131         return status;
10132 }
10133
10134 /****************************************************************
10135  _spoolss_EnumPrinterDataEx
10136 ****************************************************************/
10137
10138 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10139                                   struct spoolss_EnumPrinterDataEx *r)
10140 {
10141         uint32_t        count = 0;
10142         struct spoolss_PrinterEnumValues *info = NULL;
10143         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10144         int             snum;
10145         WERROR          result;
10146
10147         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10148
10149         *r->out.count = 0;
10150         *r->out.needed = 0;
10151         *r->out.info = NULL;
10152
10153         if (!Printer) {
10154                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10155                         OUR_HANDLE(r->in.handle)));
10156                 return WERR_BADFID;
10157         }
10158
10159         /*
10160          * first check for a keyname of NULL or "".  Win2k seems to send
10161          * this a lot and we should send back WERR_INVALID_PARAM
10162          * no need to spend time looking up the printer in this case.
10163          * --jerry
10164          */
10165
10166         if (!strlen(r->in.key_name)) {
10167                 result = WERR_INVALID_PARAM;
10168                 goto done;
10169         }
10170
10171         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10172                 return WERR_BADFID;
10173         }
10174
10175         /* now look for a match on the key name */
10176         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10177                                             get_session_info_system(),
10178                                             p->msg_ctx,
10179                                             lp_const_servicename(snum),
10180                                             r->in.key_name,
10181                                             &count,
10182                                             &info);
10183         if (!W_ERROR_IS_OK(result)) {
10184                 goto done;
10185         }
10186
10187 #if 0 /* FIXME - gd */
10188         /* housekeeping information in the reply */
10189
10190         /* Fix from Martin Zielinski <mz@seh.de> - ensure
10191          * the hand marshalled container size is a multiple
10192          * of 4 bytes for RPC alignment.
10193          */
10194
10195         if (needed % 4) {
10196                 needed += 4-(needed % 4);
10197         }
10198 #endif
10199         *r->out.count   = count;
10200         *r->out.info    = info;
10201
10202  done:
10203         if (!W_ERROR_IS_OK(result)) {
10204                 return result;
10205         }
10206
10207         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10208                                                spoolss_EnumPrinterDataEx,
10209                                                *r->out.info,
10210                                                *r->out.count);
10211         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10212         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10213
10214         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10215 }
10216
10217 /****************************************************************************
10218 ****************************************************************************/
10219
10220 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10221                                                  const char *servername,
10222                                                  const char *environment,
10223                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
10224 {
10225         WERROR werr;
10226         char *path = NULL;
10227
10228         werr = compose_spoolss_server_path(mem_ctx,
10229                                            servername,
10230                                            environment,
10231                                            SPOOLSS_PRTPROCS_PATH,
10232                                            &path);
10233         if (!W_ERROR_IS_OK(werr)) {
10234                 return werr;
10235         }
10236
10237         DEBUG(4,("print processor directory: [%s]\n", path));
10238
10239         r->directory_name = path;
10240
10241         return WERR_OK;
10242 }
10243
10244 /****************************************************************
10245  _spoolss_GetPrintProcessorDirectory
10246 ****************************************************************/
10247
10248 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10249                                            struct spoolss_GetPrintProcessorDirectory *r)
10250 {
10251         WERROR result;
10252         char *prnproc_share = NULL;
10253         bool prnproc_share_exists = false;
10254         int snum;
10255
10256         /* that's an [in out] buffer */
10257
10258         if (!r->in.buffer && (r->in.offered != 0)) {
10259                 result = WERR_INVALID_PARAM;
10260                 goto err_info_free;
10261         }
10262
10263         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10264                 r->in.level));
10265
10266         *r->out.needed = 0;
10267
10268         /* r->in.level is ignored */
10269
10270         /* We always should reply with a local print processor directory so that
10271          * users are not forced to have a [prnproc$] share on the Samba spoolss
10272          * server, if users decide to do so, lets announce it though - Guenther */
10273
10274         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10275         if (!prnproc_share) {
10276                 result = WERR_NOMEM;
10277                 goto err_info_free;
10278         }
10279         if (snum != -1) {
10280                 prnproc_share_exists = true;
10281         }
10282
10283         result = getprintprocessordirectory_level_1(p->mem_ctx,
10284                                                     prnproc_share_exists ? r->in.server : NULL,
10285                                                     r->in.environment,
10286                                                     &r->out.info->info1);
10287         if (!W_ERROR_IS_OK(result)) {
10288                 goto err_info_free;
10289         }
10290
10291         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10292                                                                                    r->out.info, r->in.level);
10293         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10294
10295         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10296
10297 err_info_free:
10298         TALLOC_FREE(r->out.info);
10299         return result;
10300 }
10301
10302 /*******************************************************************
10303  ********************************************************************/
10304
10305 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10306                                const char *dllname)
10307 {
10308         enum ndr_err_code ndr_err;
10309         struct spoolss_MonitorUi ui;
10310
10311         ui.dll_name = dllname;
10312
10313         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10314                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10315         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10316                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10317         }
10318         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10319 }
10320
10321 /*******************************************************************
10322  Streams the monitor UI DLL name in UNICODE
10323 *******************************************************************/
10324
10325 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10326                                struct security_token *token, DATA_BLOB *in,
10327                                DATA_BLOB *out, uint32_t *needed)
10328 {
10329         const char *dllname = "tcpmonui.dll";
10330
10331         *needed = (strlen(dllname)+1) * 2;
10332
10333         if (out->length < *needed) {
10334                 return WERR_INSUFFICIENT_BUFFER;
10335         }
10336
10337         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10338                 return WERR_NOMEM;
10339         }
10340
10341         return WERR_OK;
10342 }
10343
10344 /*******************************************************************
10345  ********************************************************************/
10346
10347 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10348                              struct spoolss_PortData1 *port1,
10349                              const DATA_BLOB *buf)
10350 {
10351         enum ndr_err_code ndr_err;
10352         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10353                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10354         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10355                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10356         }
10357         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10358 }
10359
10360 /*******************************************************************
10361  ********************************************************************/
10362
10363 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10364                              struct spoolss_PortData2 *port2,
10365                              const DATA_BLOB *buf)
10366 {
10367         enum ndr_err_code ndr_err;
10368         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10369                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10370         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10371                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10372         }
10373         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10374 }
10375
10376 /*******************************************************************
10377  Create a new TCP/IP port
10378 *******************************************************************/
10379
10380 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10381                              struct security_token *token, DATA_BLOB *in,
10382                              DATA_BLOB *out, uint32_t *needed)
10383 {
10384         struct spoolss_PortData1 port1;
10385         struct spoolss_PortData2 port2;
10386         char *device_uri = NULL;
10387         uint32_t version;
10388
10389         const char *portname;
10390         const char *hostaddress;
10391         const char *queue;
10392         uint32_t port_number;
10393         uint32_t protocol;
10394
10395         /* peek for spoolss_PortData version */
10396
10397         if (!in || (in->length < (128 + 4))) {
10398                 return WERR_GENERAL_FAILURE;
10399         }
10400
10401         version = IVAL(in->data, 128);
10402
10403         switch (version) {
10404                 case 1:
10405                         ZERO_STRUCT(port1);
10406
10407                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10408                                 return WERR_NOMEM;
10409                         }
10410
10411                         portname        = port1.portname;
10412                         hostaddress     = port1.hostaddress;
10413                         queue           = port1.queue;
10414                         protocol        = port1.protocol;
10415                         port_number     = port1.port_number;
10416
10417                         break;
10418                 case 2:
10419                         ZERO_STRUCT(port2);
10420
10421                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10422                                 return WERR_NOMEM;
10423                         }
10424
10425                         portname        = port2.portname;
10426                         hostaddress     = port2.hostaddress;
10427                         queue           = port2.queue;
10428                         protocol        = port2.protocol;
10429                         port_number     = port2.port_number;
10430
10431                         break;
10432                 default:
10433                         DEBUG(1,("xcvtcp_addport: "
10434                                 "unknown version of port_data: %d\n", version));
10435                         return WERR_UNKNOWN_PORT;
10436         }
10437
10438         /* create the device URI and call the add_port_hook() */
10439
10440         switch (protocol) {
10441         case PROTOCOL_RAWTCP_TYPE:
10442                 device_uri = talloc_asprintf(mem_ctx,
10443                                 "socket://%s:%d/", hostaddress,
10444                                 port_number);
10445                 break;
10446
10447         case PROTOCOL_LPR_TYPE:
10448                 device_uri = talloc_asprintf(mem_ctx,
10449                         "lpr://%s/%s", hostaddress, queue );
10450                 break;
10451
10452         default:
10453                 return WERR_UNKNOWN_PORT;
10454         }
10455
10456         if (!device_uri) {
10457                 return WERR_NOMEM;
10458         }
10459
10460         return add_port_hook(mem_ctx, token, portname, device_uri);
10461 }
10462
10463 /*******************************************************************
10464 *******************************************************************/
10465
10466 struct xcv_api_table xcvtcp_cmds[] = {
10467         { "MonitorUI",  xcvtcp_monitorui },
10468         { "AddPort",    xcvtcp_addport},
10469         { NULL,         NULL }
10470 };
10471
10472 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10473                                      struct security_token *token, const char *command,
10474                                      DATA_BLOB *inbuf,
10475                                      DATA_BLOB *outbuf,
10476                                      uint32_t *needed )
10477 {
10478         int i;
10479
10480         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10481
10482         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10483                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10484                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10485         }
10486
10487         return WERR_BADFUNC;
10488 }
10489
10490 /*******************************************************************
10491 *******************************************************************/
10492 #if 0   /* don't support management using the "Local Port" monitor */
10493
10494 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10495                                  struct security_token *token, DATA_BLOB *in,
10496                                  DATA_BLOB *out, uint32_t *needed)
10497 {
10498         const char *dllname = "localui.dll";
10499
10500         *needed = (strlen(dllname)+1) * 2;
10501
10502         if (out->length < *needed) {
10503                 return WERR_INSUFFICIENT_BUFFER;
10504         }
10505
10506         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10507                 return WERR_NOMEM;
10508         }
10509
10510         return WERR_OK;
10511 }
10512
10513 /*******************************************************************
10514 *******************************************************************/
10515
10516 struct xcv_api_table xcvlocal_cmds[] = {
10517         { "MonitorUI",  xcvlocal_monitorui },
10518         { NULL,         NULL }
10519 };
10520 #else
10521 struct xcv_api_table xcvlocal_cmds[] = {
10522         { NULL,         NULL }
10523 };
10524 #endif
10525
10526
10527
10528 /*******************************************************************
10529 *******************************************************************/
10530
10531 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10532                                        struct security_token *token, const char *command,
10533                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10534                                        uint32_t *needed)
10535 {
10536         int i;
10537
10538         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10539
10540         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10541                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10542                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10543         }
10544         return WERR_BADFUNC;
10545 }
10546
10547 /****************************************************************
10548  _spoolss_XcvData
10549 ****************************************************************/
10550
10551 WERROR _spoolss_XcvData(struct pipes_struct *p,
10552                         struct spoolss_XcvData *r)
10553 {
10554         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10555         DATA_BLOB out_data = data_blob_null;
10556         WERROR werror;
10557
10558         if (!Printer) {
10559                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10560                         OUR_HANDLE(r->in.handle)));
10561                 return WERR_BADFID;
10562         }
10563
10564         /* Has to be a handle to the TCP/IP port monitor */
10565
10566         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10567                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10568                 return WERR_BADFID;
10569         }
10570
10571         /* requires administrative access to the server */
10572
10573         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10574                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10575                 return WERR_ACCESS_DENIED;
10576         }
10577
10578         /* Allocate the outgoing buffer */
10579
10580         if (r->in.out_data_size) {
10581                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10582                 if (out_data.data == NULL) {
10583                         return WERR_NOMEM;
10584                 }
10585         }
10586
10587         switch ( Printer->printer_type ) {
10588         case SPLHND_PORTMON_TCP:
10589                 werror = process_xcvtcp_command(p->mem_ctx,
10590                                                 p->session_info->security_token,
10591                                                 r->in.function_name,
10592                                                 &r->in.in_data, &out_data,
10593                                                 r->out.needed);
10594                 break;
10595         case SPLHND_PORTMON_LOCAL:
10596                 werror = process_xcvlocal_command(p->mem_ctx,
10597                                                   p->session_info->security_token,
10598                                                   r->in.function_name,
10599                                                   &r->in.in_data, &out_data,
10600                                                   r->out.needed);
10601                 break;
10602         default:
10603                 werror = WERR_INVALID_PRINT_MONITOR;
10604         }
10605
10606         if (!W_ERROR_IS_OK(werror)) {
10607                 return werror;
10608         }
10609
10610         *r->out.status_code = 0;
10611
10612         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10613                 memcpy(r->out.out_data, out_data.data,
10614                         MIN(r->in.out_data_size, out_data.length));
10615         }
10616
10617         return WERR_OK;
10618 }
10619
10620 /****************************************************************
10621  _spoolss_AddPrintProcessor
10622 ****************************************************************/
10623
10624 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10625                                   struct spoolss_AddPrintProcessor *r)
10626 {
10627         /* for now, just indicate success and ignore the add.  We'll
10628            automatically set the winprint processor for printer
10629            entries later.  Used to debug the LexMark Optra S 1855 PCL
10630            driver --jerry */
10631
10632         return WERR_OK;
10633 }
10634
10635 /****************************************************************
10636  _spoolss_AddPort
10637 ****************************************************************/
10638
10639 WERROR _spoolss_AddPort(struct pipes_struct *p,
10640                         struct spoolss_AddPort *r)
10641 {
10642         /* do what w2k3 does */
10643
10644         return WERR_NOT_SUPPORTED;
10645 }
10646
10647 /****************************************************************
10648  _spoolss_GetPrinterDriver
10649 ****************************************************************/
10650
10651 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10652                                  struct spoolss_GetPrinterDriver *r)
10653 {
10654         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10655         return WERR_NOT_SUPPORTED;
10656 }
10657
10658 /****************************************************************
10659  _spoolss_ReadPrinter
10660 ****************************************************************/
10661
10662 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10663                             struct spoolss_ReadPrinter *r)
10664 {
10665         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10666         return WERR_NOT_SUPPORTED;
10667 }
10668
10669 /****************************************************************
10670  _spoolss_WaitForPrinterChange
10671 ****************************************************************/
10672
10673 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10674                                      struct spoolss_WaitForPrinterChange *r)
10675 {
10676         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10677         return WERR_NOT_SUPPORTED;
10678 }
10679
10680 /****************************************************************
10681  _spoolss_ConfigurePort
10682 ****************************************************************/
10683
10684 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10685                               struct spoolss_ConfigurePort *r)
10686 {
10687         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10688         return WERR_NOT_SUPPORTED;
10689 }
10690
10691 /****************************************************************
10692  _spoolss_DeletePort
10693 ****************************************************************/
10694
10695 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10696                            struct spoolss_DeletePort *r)
10697 {
10698         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10699         return WERR_NOT_SUPPORTED;
10700 }
10701
10702 /****************************************************************
10703  _spoolss_CreatePrinterIC
10704 ****************************************************************/
10705
10706 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10707                                 struct spoolss_CreatePrinterIC *r)
10708 {
10709         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10710         return WERR_NOT_SUPPORTED;
10711 }
10712
10713 /****************************************************************
10714  _spoolss_PlayGDIScriptOnPrinterIC
10715 ****************************************************************/
10716
10717 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10718                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10719 {
10720         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10721         return WERR_NOT_SUPPORTED;
10722 }
10723
10724 /****************************************************************
10725  _spoolss_DeletePrinterIC
10726 ****************************************************************/
10727
10728 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10729                                 struct spoolss_DeletePrinterIC *r)
10730 {
10731         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10732         return WERR_NOT_SUPPORTED;
10733 }
10734
10735 /****************************************************************
10736  _spoolss_AddPrinterConnection
10737 ****************************************************************/
10738
10739 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10740                                      struct spoolss_AddPrinterConnection *r)
10741 {
10742         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10743         return WERR_NOT_SUPPORTED;
10744 }
10745
10746 /****************************************************************
10747  _spoolss_DeletePrinterConnection
10748 ****************************************************************/
10749
10750 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10751                                         struct spoolss_DeletePrinterConnection *r)
10752 {
10753         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10754         return WERR_NOT_SUPPORTED;
10755 }
10756
10757 /****************************************************************
10758  _spoolss_PrinterMessageBox
10759 ****************************************************************/
10760
10761 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10762                                   struct spoolss_PrinterMessageBox *r)
10763 {
10764         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10765         return WERR_NOT_SUPPORTED;
10766 }
10767
10768 /****************************************************************
10769  _spoolss_AddMonitor
10770 ****************************************************************/
10771
10772 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10773                            struct spoolss_AddMonitor *r)
10774 {
10775         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10776         return WERR_NOT_SUPPORTED;
10777 }
10778
10779 /****************************************************************
10780  _spoolss_DeleteMonitor
10781 ****************************************************************/
10782
10783 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10784                               struct spoolss_DeleteMonitor *r)
10785 {
10786         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10787         return WERR_NOT_SUPPORTED;
10788 }
10789
10790 /****************************************************************
10791  _spoolss_DeletePrintProcessor
10792 ****************************************************************/
10793
10794 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10795                                      struct spoolss_DeletePrintProcessor *r)
10796 {
10797         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10798         return WERR_NOT_SUPPORTED;
10799 }
10800
10801 /****************************************************************
10802  _spoolss_AddPrintProvidor
10803 ****************************************************************/
10804
10805 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10806                                  struct spoolss_AddPrintProvidor *r)
10807 {
10808         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10809         return WERR_NOT_SUPPORTED;
10810 }
10811
10812 /****************************************************************
10813  _spoolss_DeletePrintProvidor
10814 ****************************************************************/
10815
10816 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10817                                     struct spoolss_DeletePrintProvidor *r)
10818 {
10819         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10820         return WERR_NOT_SUPPORTED;
10821 }
10822
10823 /****************************************************************
10824  _spoolss_FindFirstPrinterChangeNotification
10825 ****************************************************************/
10826
10827 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10828                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10829 {
10830         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10831         return WERR_NOT_SUPPORTED;
10832 }
10833
10834 /****************************************************************
10835  _spoolss_FindNextPrinterChangeNotification
10836 ****************************************************************/
10837
10838 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10839                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10840 {
10841         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10842         return WERR_NOT_SUPPORTED;
10843 }
10844
10845 /****************************************************************
10846  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10847 ****************************************************************/
10848
10849 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10850                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10851 {
10852         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10853         return WERR_NOT_SUPPORTED;
10854 }
10855
10856 /****************************************************************
10857  _spoolss_ReplyOpenPrinter
10858 ****************************************************************/
10859
10860 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10861                                  struct spoolss_ReplyOpenPrinter *r)
10862 {
10863         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10864         return WERR_NOT_SUPPORTED;
10865 }
10866
10867 /****************************************************************
10868  _spoolss_RouterReplyPrinter
10869 ****************************************************************/
10870
10871 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10872                                    struct spoolss_RouterReplyPrinter *r)
10873 {
10874         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10875         return WERR_NOT_SUPPORTED;
10876 }
10877
10878 /****************************************************************
10879  _spoolss_ReplyClosePrinter
10880 ****************************************************************/
10881
10882 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10883                                   struct spoolss_ReplyClosePrinter *r)
10884 {
10885         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10886         return WERR_NOT_SUPPORTED;
10887 }
10888
10889 /****************************************************************
10890  _spoolss_AddPortEx
10891 ****************************************************************/
10892
10893 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10894                           struct spoolss_AddPortEx *r)
10895 {
10896         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10897         return WERR_NOT_SUPPORTED;
10898 }
10899
10900 /****************************************************************
10901  _spoolss_RouterFindFirstPrinterChangeNotification
10902 ****************************************************************/
10903
10904 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10905                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10906 {
10907         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10908         return WERR_NOT_SUPPORTED;
10909 }
10910
10911 /****************************************************************
10912  _spoolss_SpoolerInit
10913 ****************************************************************/
10914
10915 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10916                             struct spoolss_SpoolerInit *r)
10917 {
10918         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10919         return WERR_NOT_SUPPORTED;
10920 }
10921
10922 /****************************************************************
10923  _spoolss_ResetPrinterEx
10924 ****************************************************************/
10925
10926 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10927                                struct spoolss_ResetPrinterEx *r)
10928 {
10929         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10930         return WERR_NOT_SUPPORTED;
10931 }
10932
10933 /****************************************************************
10934  _spoolss_RouterReplyPrinterEx
10935 ****************************************************************/
10936
10937 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10938                                      struct spoolss_RouterReplyPrinterEx *r)
10939 {
10940         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10941         return WERR_NOT_SUPPORTED;
10942 }
10943
10944 /****************************************************************
10945  _spoolss_44
10946 ****************************************************************/
10947
10948 WERROR _spoolss_44(struct pipes_struct *p,
10949                    struct spoolss_44 *r)
10950 {
10951         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10952         return WERR_NOT_SUPPORTED;
10953 }
10954
10955 /****************************************************************
10956  _spoolss_SetPort
10957 ****************************************************************/
10958
10959 WERROR _spoolss_SetPort(struct pipes_struct *p,
10960                         struct spoolss_SetPort *r)
10961 {
10962         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10963         return WERR_NOT_SUPPORTED;
10964 }
10965
10966 /****************************************************************
10967  _spoolss_4a
10968 ****************************************************************/
10969
10970 WERROR _spoolss_4a(struct pipes_struct *p,
10971                    struct spoolss_4a *r)
10972 {
10973         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10974         return WERR_NOT_SUPPORTED;
10975 }
10976
10977 /****************************************************************
10978  _spoolss_4b
10979 ****************************************************************/
10980
10981 WERROR _spoolss_4b(struct pipes_struct *p,
10982                    struct spoolss_4b *r)
10983 {
10984         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10985         return WERR_NOT_SUPPORTED;
10986 }
10987
10988 /****************************************************************
10989  _spoolss_4c
10990 ****************************************************************/
10991
10992 WERROR _spoolss_4c(struct pipes_struct *p,
10993                    struct spoolss_4c *r)
10994 {
10995         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10996         return WERR_NOT_SUPPORTED;
10997 }
10998
10999 /****************************************************************
11000  _spoolss_53
11001 ****************************************************************/
11002
11003 WERROR _spoolss_53(struct pipes_struct *p,
11004                    struct spoolss_53 *r)
11005 {
11006         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11007         return WERR_NOT_SUPPORTED;
11008 }
11009
11010 /****************************************************************
11011  _spoolss_AddPerMachineConnection
11012 ****************************************************************/
11013
11014 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11015                                         struct spoolss_AddPerMachineConnection *r)
11016 {
11017         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11018         return WERR_NOT_SUPPORTED;
11019 }
11020
11021 /****************************************************************
11022  _spoolss_DeletePerMachineConnection
11023 ****************************************************************/
11024
11025 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11026                                            struct spoolss_DeletePerMachineConnection *r)
11027 {
11028         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11029         return WERR_NOT_SUPPORTED;
11030 }
11031
11032 /****************************************************************
11033  _spoolss_EnumPerMachineConnections
11034 ****************************************************************/
11035
11036 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11037                                           struct spoolss_EnumPerMachineConnections *r)
11038 {
11039         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11040         return WERR_NOT_SUPPORTED;
11041 }
11042
11043 /****************************************************************
11044  _spoolss_5a
11045 ****************************************************************/
11046
11047 WERROR _spoolss_5a(struct pipes_struct *p,
11048                    struct spoolss_5a *r)
11049 {
11050         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11051         return WERR_NOT_SUPPORTED;
11052 }
11053
11054 /****************************************************************
11055  _spoolss_5b
11056 ****************************************************************/
11057
11058 WERROR _spoolss_5b(struct pipes_struct *p,
11059                    struct spoolss_5b *r)
11060 {
11061         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11062         return WERR_NOT_SUPPORTED;
11063 }
11064
11065 /****************************************************************
11066  _spoolss_5c
11067 ****************************************************************/
11068
11069 WERROR _spoolss_5c(struct pipes_struct *p,
11070                    struct spoolss_5c *r)
11071 {
11072         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11073         return WERR_NOT_SUPPORTED;
11074 }
11075
11076 /****************************************************************
11077  _spoolss_5d
11078 ****************************************************************/
11079
11080 WERROR _spoolss_5d(struct pipes_struct *p,
11081                    struct spoolss_5d *r)
11082 {
11083         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11084         return WERR_NOT_SUPPORTED;
11085 }
11086
11087 /****************************************************************
11088  _spoolss_5e
11089 ****************************************************************/
11090
11091 WERROR _spoolss_5e(struct pipes_struct *p,
11092                    struct spoolss_5e *r)
11093 {
11094         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11095         return WERR_NOT_SUPPORTED;
11096 }
11097
11098 /****************************************************************
11099  _spoolss_5f
11100 ****************************************************************/
11101
11102 WERROR _spoolss_5f(struct pipes_struct *p,
11103                    struct spoolss_5f *r)
11104 {
11105         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11106         return WERR_NOT_SUPPORTED;
11107 }
11108
11109 /****************************************************************
11110  _spoolss_60
11111 ****************************************************************/
11112
11113 WERROR _spoolss_60(struct pipes_struct *p,
11114                    struct spoolss_60 *r)
11115 {
11116         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11117         return WERR_NOT_SUPPORTED;
11118 }
11119
11120 /****************************************************************
11121  _spoolss_RpcSendRecvBidiData
11122 ****************************************************************/
11123
11124 WERROR _spoolss_RpcSendRecvBidiData(struct pipes_struct *p,
11125                                     struct spoolss_RpcSendRecvBidiData *r)
11126 {
11127         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11128         return WERR_NOT_SUPPORTED;
11129 }
11130
11131 /****************************************************************
11132  _spoolss_62
11133 ****************************************************************/
11134
11135 WERROR _spoolss_62(struct pipes_struct *p,
11136                    struct spoolss_62 *r)
11137 {
11138         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11139         return WERR_NOT_SUPPORTED;
11140 }
11141
11142 /****************************************************************
11143  _spoolss_63
11144 ****************************************************************/
11145
11146 WERROR _spoolss_63(struct pipes_struct *p,
11147                    struct spoolss_63 *r)
11148 {
11149         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11150         return WERR_NOT_SUPPORTED;
11151 }
11152
11153 /****************************************************************
11154  _spoolss_64
11155 ****************************************************************/
11156
11157 WERROR _spoolss_64(struct pipes_struct *p,
11158                    struct spoolss_64 *r)
11159 {
11160         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11161         return WERR_NOT_SUPPORTED;
11162 }
11163
11164 /****************************************************************
11165  _spoolss_65
11166 ****************************************************************/
11167
11168 WERROR _spoolss_65(struct pipes_struct *p,
11169                    struct spoolss_65 *r)
11170 {
11171         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11172         return WERR_NOT_SUPPORTED;
11173 }
11174
11175 /****************************************************************
11176  _spoolss_GetCorePrinterDrivers
11177 ****************************************************************/
11178
11179 HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11180                                        struct spoolss_GetCorePrinterDrivers *r)
11181 {
11182         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11183         return HRES_ERROR_NOT_SUPPORTED;
11184 }
11185
11186 /****************************************************************
11187  _spoolss_67
11188 ****************************************************************/
11189
11190 WERROR _spoolss_67(struct pipes_struct *p,
11191                    struct spoolss_67 *r)
11192 {
11193         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11194         return WERR_NOT_SUPPORTED;
11195 }
11196
11197 /****************************************************************
11198  _spoolss_GetPrinterDriverPackagePath
11199 ****************************************************************/
11200
11201 HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11202                                              struct spoolss_GetPrinterDriverPackagePath *r)
11203 {
11204         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11205         return HRES_ERROR_NOT_SUPPORTED;
11206 }
11207
11208 /****************************************************************
11209  _spoolss_69
11210 ****************************************************************/
11211
11212 WERROR _spoolss_69(struct pipes_struct *p,
11213                    struct spoolss_69 *r)
11214 {
11215         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11216         return WERR_NOT_SUPPORTED;
11217 }
11218
11219 /****************************************************************
11220  _spoolss_6a
11221 ****************************************************************/
11222
11223 WERROR _spoolss_6a(struct pipes_struct *p,
11224                    struct spoolss_6a *r)
11225 {
11226         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11227         return WERR_NOT_SUPPORTED;
11228 }
11229
11230 /****************************************************************
11231  _spoolss_6b
11232 ****************************************************************/
11233
11234 WERROR _spoolss_6b(struct pipes_struct *p,
11235                    struct spoolss_6b *r)
11236 {
11237         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11238         return WERR_NOT_SUPPORTED;
11239 }
11240
11241 /****************************************************************
11242  _spoolss_6c
11243 ****************************************************************/
11244
11245 WERROR _spoolss_6c(struct pipes_struct *p,
11246                    struct spoolss_6c *r)
11247 {
11248         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11249         return WERR_NOT_SUPPORTED;
11250 }
11251
11252 /****************************************************************
11253  _spoolss_6d
11254 ****************************************************************/
11255
11256 WERROR _spoolss_6d(struct pipes_struct *p,
11257                    struct spoolss_6d *r)
11258 {
11259         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11260         return WERR_NOT_SUPPORTED;
11261 }
11262
11263 /****************************************************************
11264  _spoolss_RpcGetJobNamedPropertyValue
11265 ****************************************************************/
11266
11267 WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
11268                                             struct spoolss_RpcGetJobNamedPropertyValue *r)
11269 {
11270         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11271         return WERR_NOT_SUPPORTED;
11272 }
11273
11274 /****************************************************************
11275  _spoolss_RpcSetJobNamedProperty
11276 ****************************************************************/
11277
11278 WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
11279                                        struct spoolss_RpcSetJobNamedProperty *r)
11280 {
11281         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11282         return WERR_NOT_SUPPORTED;
11283 }
11284
11285 /****************************************************************
11286  _spoolss_RpcDeleteJobNamedProperty
11287 ****************************************************************/
11288
11289 WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
11290                                           struct spoolss_RpcDeleteJobNamedProperty *r)
11291 {
11292         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11293         return WERR_NOT_SUPPORTED;
11294 }
11295
11296 /****************************************************************
11297  _spoolss_RpcEnumJobNamedProperties
11298 ****************************************************************/
11299
11300 WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
11301                                           struct spoolss_RpcEnumJobNamedProperties *r)
11302 {
11303         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11304         return WERR_NOT_SUPPORTED;
11305 }