Fix a few "might be uninitialized" errors
[samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "lib/util/util_file.h"
32 #include "libsmb/namequery.h"
33 #include "ntdomain.h"
34 #include "nt_printing.h"
35 #include "srv_spoolss_util.h"
36 #include "librpc/gen_ndr/ndr_spoolss.h"
37 #include "librpc/gen_ndr/ndr_spoolss_scompat.h"
38 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
39 #include "rpc_client/init_spoolss.h"
40 #include "rpc_client/cli_pipe.h"
41 #include "../libcli/security/security.h"
42 #include "librpc/gen_ndr/ndr_security.h"
43 #include "registry.h"
44 #include "include/printing.h"
45 #include "secrets.h"
46 #include "../librpc/gen_ndr/netlogon.h"
47 #include "rpc_misc.h"
48 #include "printing/notify.h"
49 #include "serverid.h"
50 #include "../libcli/registry/util_reg.h"
51 #include "smbd/smbd.h"
52 #include "smbd/globals.h"
53 #include "auth.h"
54 #include "messages.h"
55 #include "rpc_server/spoolss/srv_spoolss_nt.h"
56 #include "util_tdb.h"
57 #include "libsmb/libsmb.h"
58 #include "printing/printer_list.h"
59 #include "../lib/tsocket/tsocket.h"
60 #include "rpc_client/cli_winreg_spoolss.h"
61 #include "../libcli/smb/smbXcli_base.h"
62 #include "rpc_server/spoolss/srv_spoolss_handle.h"
63 #include "lib/gencache.h"
64 #include "rpc_server/rpc_server.h"
65 #include "librpc/rpc/dcesrv_core.h"
66 #include "printing/nt_printing_migrate_internal.h"
67 #include "lib/util/string_wrappers.h"
68 #include "lib/global_contexts.h"
69
70 /* macros stolen from s4 spoolss server */
71 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
72         ((info)?ndr_size_##fn(info, level, 0):0)
73
74 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
75         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
76
77 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
78         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
79
80 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
81
82 #undef DBGC_CLASS
83 #define DBGC_CLASS DBGC_RPC_SRV
84
85 #ifndef MAX_OPEN_PRINTER_EXS
86 #define MAX_OPEN_PRINTER_EXS 50
87 #endif
88
89 #define GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT 5
90 #define GLOBAL_SPOOLSS_OS_MINOR_DEFAULT 2
91 #define GLOBAL_SPOOLSS_OS_BUILD_DEFAULT 3790
92 #define GLOBAL_SPOOLSS_ARCHITECTURE SPOOLSS_ARCHITECTURE_x64
93
94 static struct printer_handle *printers_list;
95
96 struct printer_session_counter {
97         struct printer_session_counter *next;
98         struct printer_session_counter *prev;
99
100         int snum;
101         uint32_t counter;
102 };
103
104 static struct printer_session_counter *counter_list;
105
106 struct notify_back_channel {
107         struct notify_back_channel *prev, *next;
108
109         /* associated client */
110         struct sockaddr_storage client_address;
111
112         /* print notify back-channel pipe handle*/
113         struct rpc_pipe_client *cli_pipe;
114         struct cli_state *cli;
115         uint32_t active_connections;
116 };
117
118 static struct notify_back_channel *back_channels;
119
120 /* Map generic permissions to printer object specific permissions */
121
122 const struct standard_mapping printer_std_mapping = {
123         PRINTER_READ,
124         PRINTER_WRITE,
125         PRINTER_EXECUTE,
126         PRINTER_ALL_ACCESS
127 };
128
129 /* Map generic permissions to print server object specific permissions */
130
131 const struct standard_mapping printserver_std_mapping = {
132         SERVER_READ,
133         SERVER_WRITE,
134         SERVER_EXECUTE,
135         SERVER_ALL_ACCESS
136 };
137
138 /* API table for Xcv Monitor functions */
139
140 struct xcv_api_table {
141         const char *name;
142         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
143 };
144
145 static void prune_printername_cache(void);
146
147 /********************************************************************
148  * Canonicalize servername.
149  ********************************************************************/
150
151 static const char *canon_servername(const char *servername)
152 {
153         const char *pservername = servername;
154
155         if (servername == NULL) {
156                 return "";
157         }
158
159         while (*pservername == '\\') {
160                 pservername++;
161         }
162         return pservername;
163 }
164
165 /* translate between internal status numbers and NT status numbers */
166 static int nt_printj_status(int v)
167 {
168         switch (v) {
169         case LPQ_QUEUED:
170                 return 0;
171         case LPQ_PAUSED:
172                 return JOB_STATUS_PAUSED;
173         case LPQ_SPOOLING:
174                 return JOB_STATUS_SPOOLING;
175         case LPQ_PRINTING:
176                 return JOB_STATUS_PRINTING;
177         case LPQ_ERROR:
178                 return JOB_STATUS_ERROR;
179         case LPQ_DELETING:
180                 return JOB_STATUS_DELETING;
181         case LPQ_OFFLINE:
182                 return JOB_STATUS_OFFLINE;
183         case LPQ_PAPEROUT:
184                 return JOB_STATUS_PAPEROUT;
185         case LPQ_PRINTED:
186                 return JOB_STATUS_PRINTED;
187         case LPQ_DELETED:
188                 return JOB_STATUS_DELETED;
189         case LPQ_BLOCKED:
190                 return JOB_STATUS_BLOCKED_DEVQ;
191         case LPQ_USER_INTERVENTION:
192                 return JOB_STATUS_USER_INTERVENTION;
193         }
194         return 0;
195 }
196
197 static int nt_printq_status(int v)
198 {
199         switch (v) {
200         case LPQ_PAUSED:
201                 return PRINTER_STATUS_PAUSED;
202         case LPQ_QUEUED:
203         case LPQ_SPOOLING:
204         case LPQ_PRINTING:
205                 return 0;
206         }
207         return 0;
208 }
209
210 /***************************************************************************
211  Disconnect from the client
212 ****************************************************************************/
213
214 static void srv_spoolss_replycloseprinter(int snum,
215                                           struct printer_handle *prn_hnd)
216 {
217         WERROR result;
218         NTSTATUS status;
219
220         /*
221          * Tell the specific printing tdb we no longer want messages for this printer
222          * by deregistering our PID.
223          */
224
225         if (!print_notify_deregister_pid(snum)) {
226                 DEBUG(0, ("Failed to register our pid for printer %s\n",
227                           lp_const_servicename(snum)));
228         }
229
230         /* weird if the test succeeds !!! */
231         if (prn_hnd->notify.cli_chan == NULL ||
232             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
233             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
234             prn_hnd->notify.cli_chan->active_connections == 0) {
235                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
236                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
237                 TALLOC_FREE(prn_hnd->notify.cli_chan);
238                 return;
239         }
240
241         status = dcerpc_spoolss_ReplyClosePrinter(
242                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
243                                         talloc_tos(),
244                                         &prn_hnd->notify.cli_hnd,
245                                         &result);
246         if (!NT_STATUS_IS_OK(status)) {
247                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
248                           nt_errstr(status)));
249                 result = ntstatus_to_werror(status);
250         } else if (!W_ERROR_IS_OK(result)) {
251                 DEBUG(0, ("reply_close_printer failed [%s].\n",
252                           win_errstr(result)));
253         }
254
255         /* if it's the last connection, deconnect the IPC$ share */
256         if (prn_hnd->notify.cli_chan->active_connections == 1) {
257
258                 cli_shutdown(prn_hnd->notify.cli_chan->cli);
259                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
260                 TALLOC_FREE(prn_hnd->notify.cli_chan);
261
262                 if (prn_hnd->notify.msg_ctx != NULL) {
263                         messaging_deregister(prn_hnd->notify.msg_ctx,
264                                              MSG_PRINTER_NOTIFY2, NULL);
265                 }
266         }
267
268         if (prn_hnd->notify.cli_chan) {
269                 prn_hnd->notify.cli_chan->active_connections--;
270                 prn_hnd->notify.cli_chan = NULL;
271         }
272 }
273
274 /****************************************************************************
275  Functions to free a printer entry datastruct.
276 ****************************************************************************/
277
278 static int printer_entry_destructor(struct printer_handle *Printer)
279 {
280         if (Printer->notify.cli_chan != NULL &&
281             Printer->notify.cli_chan->active_connections > 0) {
282                 int snum = -1;
283
284                 switch(Printer->printer_type) {
285                 case SPLHND_SERVER:
286                         srv_spoolss_replycloseprinter(snum, Printer);
287                         break;
288
289                 case SPLHND_PRINTER:
290                         snum = print_queue_snum(Printer->sharename);
291                         if (snum != -1) {
292                                 srv_spoolss_replycloseprinter(snum, Printer);
293                         }
294                         break;
295                 default:
296                         break;
297                 }
298         }
299
300         Printer->notify.flags=0;
301         Printer->notify.options=0;
302         Printer->notify.localmachine[0]='\0';
303         Printer->notify.printerlocal=0;
304         TALLOC_FREE(Printer->notify.option);
305         TALLOC_FREE(Printer->devmode);
306
307         /* Remove from the internal list. */
308         DLIST_REMOVE(printers_list, Printer);
309         return 0;
310 }
311
312 /****************************************************************************
313   find printer index by handle
314 ****************************************************************************/
315
316 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
317                                                         struct policy_handle *hnd)
318 {
319         struct printer_handle *find_printer = NULL;
320         NTSTATUS status;
321
322         find_printer = find_policy_by_hnd(p,
323                                           hnd,
324                                           DCESRV_HANDLE_ANY,
325                                           struct printer_handle,
326                                           &status);
327         if (!NT_STATUS_IS_OK(status)) {
328                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: %s\n",
329                          nt_errstr(status)));
330                 return NULL;
331         }
332
333         return find_printer;
334 }
335
336 /****************************************************************************
337  Close printer index by handle.
338 ****************************************************************************/
339
340 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
341 {
342         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
343
344         if (!Printer) {
345                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
346                         OUR_HANDLE(hnd)));
347                 return false;
348         }
349
350         close_policy_hnd(p, hnd);
351
352         return true;
353 }
354
355 /****************************************************************************
356  Delete a printer given a handle.
357 ****************************************************************************/
358
359 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
360                                   const char *sharename,
361                                   struct messaging_context *msg_ctx)
362 {
363         const struct loadparm_substitution *lp_sub =
364                 loadparm_s3_global_substitution();
365         char *cmd = lp_deleteprinter_command(talloc_tos(), lp_sub);
366         char *command = NULL;
367         int ret;
368         bool is_print_op = false;
369
370         /* can't fail if we don't try */
371
372         if ( !*cmd )
373                 return WERR_OK;
374
375         command = talloc_asprintf(ctx,
376                         "%s \"%s\"",
377                         cmd, sharename);
378         if (!command) {
379                 return WERR_NOT_ENOUGH_MEMORY;
380         }
381         if ( token )
382                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
383
384         DEBUG(10,("Running [%s]\n", command));
385
386         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
387
388         if ( is_print_op )
389                 become_root();
390
391         ret = smbrun(command, NULL, NULL);
392         if (ret == 0) {
393                 /* Tell everyone we updated smb.conf. */
394                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
395         }
396
397         if ( is_print_op )
398                 unbecome_root();
399
400         /********** END SePrintOperatorPrivlege BLOCK **********/
401
402         DEBUGADD(10,("returned [%d]\n", ret));
403
404         TALLOC_FREE(command);
405
406         if (ret != 0)
407                 return WERR_INVALID_HANDLE; /* What to return here? */
408
409         return WERR_OK;
410 }
411
412 /****************************************************************************
413  Delete a printer given a handle.
414 ****************************************************************************/
415
416 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
417 {
418         struct dcesrv_call_state *dce_call = p->dce_call;
419         struct auth_session_info *session_info =
420                 dcesrv_call_session_info(dce_call);
421         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
422         WERROR result;
423
424         if (!Printer) {
425                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
426                         OUR_HANDLE(hnd)));
427                 return WERR_INVALID_HANDLE;
428         }
429
430         /*
431          * It turns out that Windows allows delete printer on a handle
432          * opened by an admin user, then used on a pipe handle created
433          * by an anonymous user..... but they're working on security.... riiight !
434          * JRA.
435          */
436
437         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
438                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
439                 return WERR_ACCESS_DENIED;
440         }
441
442         /* this does not need a become root since the access check has been
443            done on the handle already */
444
445         result = winreg_delete_printer_key_internal(p->mem_ctx,
446                                            get_session_info_system(),
447                                            p->msg_ctx,
448                                            Printer->sharename,
449                                            "");
450         if (!W_ERROR_IS_OK(result)) {
451                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
452                 return WERR_INVALID_HANDLE;
453         }
454
455         result = delete_printer_hook(p->mem_ctx, session_info->security_token,
456                                      Printer->sharename, p->msg_ctx);
457         if (!W_ERROR_IS_OK(result)) {
458                 return result;
459         }
460         prune_printername_cache();
461         return WERR_OK;
462 }
463
464 /****************************************************************************
465  Return the snum of a printer corresponding to an handle.
466 ****************************************************************************/
467
468 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
469                              int *number, struct share_params **params)
470 {
471         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
472
473         if (!Printer) {
474                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
475                         OUR_HANDLE(hnd)));
476                 return false;
477         }
478
479         switch (Printer->printer_type) {
480                 case SPLHND_PRINTER:
481                         DEBUG(4,("short name:%s\n", Printer->sharename));
482                         *number = print_queue_snum(Printer->sharename);
483                         return (*number != -1);
484                 case SPLHND_SERVER:
485                         return false;
486                 default:
487                         return false;
488         }
489 }
490
491 /****************************************************************************
492  Set printer handle type.
493  Check if it's \\server or \\server\printer
494 ****************************************************************************/
495
496 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
497 {
498         DEBUG(3,("Setting printer type=%s\n", handlename));
499
500         /* it's a print server */
501         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
502                 DEBUGADD(4,("Printer is a print server\n"));
503                 Printer->printer_type = SPLHND_SERVER;
504         }
505         /* it's a printer (set_printer_hnd_name() will handle port monitors */
506         else {
507                 DEBUGADD(4,("Printer is a printer\n"));
508                 Printer->printer_type = SPLHND_PRINTER;
509         }
510
511         return true;
512 }
513
514 static void prune_printername_cache_fn(const char *key, const char *value,
515                                        time_t timeout, void *private_data)
516 {
517         gencache_del(key);
518 }
519
520 static void prune_printername_cache(void)
521 {
522         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
523 }
524
525 /****************************************************************************
526  Set printer handle name..  Accept names like \\server, \\server\printer,
527  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
528  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
529  XcvDataPort() interface.
530 ****************************************************************************/
531
532 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
533                                    const struct auth_session_info *session_info,
534                                    struct messaging_context *msg_ctx,
535                                    struct printer_handle *Printer,
536                                    const char *handlename)
537 {
538         int snum;
539         int n_services=lp_numservices();
540         char *aprinter;
541         const char *printername;
542         const char *servername = NULL;
543         fstring sname;
544         bool found = false;
545         struct spoolss_PrinterInfo2 *info2 = NULL;
546         WERROR result;
547         char *p;
548
549         /*
550          * Hopefully nobody names his printers like this. Maybe \ or ,
551          * are illegal in printer names even?
552          */
553         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
554         char *cache_key;
555         char *tmp;
556
557         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
558                 (unsigned long)strlen(handlename)));
559
560         aprinter = discard_const_p(char, handlename);
561         if ( *handlename == '\\' ) {
562                 servername = canon_servername(handlename);
563                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
564                         *aprinter = '\0';
565                         aprinter++;
566                 }
567                 if (!is_myname_or_ipaddr(servername)) {
568                         return WERR_INVALID_PRINTER_NAME;
569                 }
570                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
571                 if (Printer->servername == NULL) {
572                         return WERR_NOT_ENOUGH_MEMORY;
573                 }
574         }
575
576         if (Printer->printer_type == SPLHND_SERVER) {
577                 return WERR_OK;
578         }
579
580         if (Printer->printer_type != SPLHND_PRINTER) {
581                 return WERR_INVALID_HANDLE;
582         }
583
584         DEBUGADD(5, ("searching for [%s]\n", aprinter));
585
586         p = strchr(aprinter, ',');
587         if (p != NULL) {
588                 char *p2 = p;
589                 p++;
590                 if (*p == ' ') {
591                         p++;
592                 }
593                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
594                         *p2 = '\0';
595                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
596                         *p2 = '\0';
597                 }
598         }
599
600         if (p) {
601                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
602         }
603
604         /* check for the Port Monitor Interface */
605         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
606                 Printer->printer_type = SPLHND_PORTMON_TCP;
607                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
608                 found = true;
609         }
610         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
611                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
612                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
613                 found = true;
614         }
615
616         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
617         if (cache_key == NULL) {
618                 return WERR_NOT_ENOUGH_MEMORY;
619         }
620
621         /*
622          * With hundreds of printers, the "for" loop iterating all
623          * shares can be quite expensive, as it is done on every
624          * OpenPrinter. The loop maps "aprinter" to "sname", the
625          * result of which we cache in gencache.
626          */
627         if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
628                 found = (strcmp(tmp, printer_not_found) != 0);
629                 if (!found) {
630                         DEBUG(4, ("Printer %s not found\n", aprinter));
631                         TALLOC_FREE(tmp);
632                         return WERR_INVALID_PRINTER_NAME;
633                 }
634                 fstrcpy(sname, tmp);
635                 TALLOC_FREE(tmp);
636         }
637
638         /* Search all sharenames first as this is easier than pulling
639            the printer_info_2 off of disk. Don't use find_service() since
640            that calls out to map_username() */
641
642         /* do another loop to look for printernames */
643         for (snum = 0; !found && snum < n_services; snum++) {
644                 const char *printer = lp_const_servicename(snum);
645
646                 /* no point going on if this is not a printer */
647                 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
648                         continue;
649                 }
650
651                 /* ignore [printers] share */
652                 if (strequal(printer, "printers")) {
653                         continue;
654                 }
655
656                 fstrcpy(sname, printer);
657                 if (strequal(aprinter, printer)) {
658                         found = true;
659                         break;
660                 }
661
662                 /* no point looking up the printer object if
663                    we aren't allowing printername != sharename */
664                 if (lp_force_printername(snum)) {
665                         continue;
666                 }
667
668                 result = winreg_get_printer_internal(mem_ctx,
669                                             session_info,
670                                             msg_ctx,
671                                             sname,
672                                             &info2);
673                 if ( !W_ERROR_IS_OK(result) ) {
674                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
675                                  sname, win_errstr(result)));
676                         continue;
677                 }
678
679                 printername = strrchr(info2->printername, '\\');
680                 if (printername == NULL) {
681                         printername = info2->printername;
682                 } else {
683                         printername++;
684                 }
685
686                 if (strequal(printername, aprinter)) {
687                         found = true;
688                         break;
689                 }
690
691                 DEBUGADD(10, ("printername: %s\n", printername));
692
693                 TALLOC_FREE(info2);
694         }
695
696         if (!found) {
697                 gencache_set(cache_key, printer_not_found,
698                              time(NULL) + 300);
699                 TALLOC_FREE(cache_key);
700                 DEBUGADD(4,("Printer not found\n"));
701                 return WERR_INVALID_PRINTER_NAME;
702         }
703
704         gencache_set(cache_key, sname, time(NULL) + 300);
705         TALLOC_FREE(cache_key);
706
707         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
708
709         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
710
711         return WERR_OK;
712 }
713
714 /****************************************************************************
715  Find first available printer slot. creates a printer handle for you.
716  ****************************************************************************/
717
718 static WERROR open_printer_hnd(struct pipes_struct *p,
719                                struct policy_handle *hnd,
720                                const char *name,
721                                uint32_t access_granted)
722 {
723         struct printer_handle *new_printer;
724         WERROR result;
725
726         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
727
728         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
729         if (new_printer == NULL) {
730                 return WERR_NOT_ENOUGH_MEMORY;
731         }
732         talloc_set_destructor(new_printer, printer_entry_destructor);
733
734         /* This also steals the printer_handle on the policy_handle */
735         if (!create_policy_hnd(p, hnd, 0, new_printer)) {
736                 TALLOC_FREE(new_printer);
737                 return WERR_INVALID_HANDLE;
738         }
739
740         /* Add to the internal list. */
741         DLIST_ADD(printers_list, new_printer);
742
743         new_printer->notify.option=NULL;
744
745         if (!set_printer_hnd_printertype(new_printer, name)) {
746                 close_printer_handle(p, hnd);
747                 return WERR_INVALID_HANDLE;
748         }
749
750         result = set_printer_hnd_name(p->mem_ctx,
751                                       get_session_info_system(),
752                                       p->msg_ctx,
753                                       new_printer, name);
754         if (!W_ERROR_IS_OK(result)) {
755                 close_printer_handle(p, hnd);
756                 return result;
757         }
758
759         new_printer->access_granted = access_granted;
760
761         DBG_INFO("%d printer handles active\n", (int)num_pipe_handles());
762
763         return WERR_OK;
764 }
765
766 /***************************************************************************
767  check to see if the client notify handle is monitoring the notification
768  given by (notify_type, notify_field).
769  **************************************************************************/
770
771 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
772                                       uint16_t notify_field)
773 {
774         return true;
775 }
776
777 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
778                                 uint16_t notify_field)
779 {
780         struct spoolss_NotifyOption *option = p->notify.option;
781         uint32_t i, j;
782
783         /*
784          * Flags should always be zero when the change notify
785          * is registered by the client's spooler.  A user Win32 app
786          * might use the flags though instead of the NOTIFY_OPTION_INFO
787          * --jerry
788          */
789
790         if (!option) {
791                 return false;
792         }
793
794         if (p->notify.flags)
795                 return is_monitoring_event_flags(
796                         p->notify.flags, notify_type, notify_field);
797
798         for (i = 0; i < option->count; i++) {
799
800                 /* Check match for notify_type */
801
802                 if (option->types[i].type != notify_type)
803                         continue;
804
805                 /* Check match for field */
806
807                 for (j = 0; j < option->types[i].count; j++) {
808                         if (option->types[i].fields[j].field == notify_field) {
809                                 return true;
810                         }
811                 }
812         }
813
814         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
815                    p->servername, p->sharename, notify_type, notify_field));
816
817         return false;
818 }
819
820 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
821         _data->data.integer[0] = _integer; \
822         _data->data.integer[1] = 0;
823
824
825 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
826         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
827         if (!_data->data.string.string) {\
828                 _data->data.string.size = 0; \
829         } \
830         _data->data.string.size = strlen_m_term(_p) * 2;
831
832 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
833         _data->data.devmode.devmode = _devmode;
834
835 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
836                                    struct tm *t,
837                                    const char **pp,
838                                    uint32_t *plen)
839 {
840         struct spoolss_Time st;
841         uint32_t len = 16;
842         char *p;
843
844         if (!init_systemtime(&st, t)) {
845                 return;
846         }
847
848         p = talloc_array(mem_ctx, char, len);
849         if (!p) {
850                 return;
851         }
852
853         /*
854          * Systemtime must be linearized as a set of UINT16's.
855          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
856          */
857
858         SSVAL(p, 0, st.year);
859         SSVAL(p, 2, st.month);
860         SSVAL(p, 4, st.day_of_week);
861         SSVAL(p, 6, st.day);
862         SSVAL(p, 8, st.hour);
863         SSVAL(p, 10, st.minute);
864         SSVAL(p, 12, st.second);
865         SSVAL(p, 14, st.millisecond);
866
867         *pp = p;
868         *plen = len;
869 }
870
871 /* Convert a notification message to a struct spoolss_Notify */
872
873 static void notify_one_value(struct spoolss_notify_msg *msg,
874                              struct spoolss_Notify *data,
875                              TALLOC_CTX *mem_ctx)
876 {
877         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
878 }
879
880 static void notify_string(struct spoolss_notify_msg *msg,
881                           struct spoolss_Notify *data,
882                           TALLOC_CTX *mem_ctx)
883 {
884         /* The length of the message includes the trailing \0 */
885
886         data->data.string.size = msg->len * 2;
887         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
888         if (!data->data.string.string) {
889                 data->data.string.size = 0;
890                 return;
891         }
892 }
893
894 static void notify_system_time(struct spoolss_notify_msg *msg,
895                                struct spoolss_Notify *data,
896                                TALLOC_CTX *mem_ctx)
897 {
898         data->data.string.string = NULL;
899         data->data.string.size = 0;
900
901         if (msg->len != sizeof(time_t)) {
902                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
903                           msg->len));
904                 return;
905         }
906
907         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
908                                &data->data.string.string,
909                                &data->data.string.size);
910 }
911
912 struct notify2_message_table {
913         const char *name;
914         void (*fn)(struct spoolss_notify_msg *msg,
915                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
916 };
917
918 static struct notify2_message_table printer_notify_table[] = {
919         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
920         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
921         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
922         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
923         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
924         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
925         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
926         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
927         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
928         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
929         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
930         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
931         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
932         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
933         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
934         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
935         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
936         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
937         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
938 };
939
940 static struct notify2_message_table job_notify_table[] = {
941         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
942         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
943         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
944         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
945         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
946         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
947         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
948         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
949         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
950         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
951         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
952         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
953         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
954         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
955         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
956         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
957         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
958         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
959         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
960         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
961         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
962         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
963         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
964         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
965 };
966
967
968 /***********************************************************************
969  Allocate talloc context for container object
970  **********************************************************************/
971
972 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
973 {
974         if ( !ctr )
975                 return;
976
977         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
978
979         return;
980 }
981
982 /***********************************************************************
983  release all allocated memory and zero out structure
984  **********************************************************************/
985
986 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
987 {
988         if ( !ctr )
989                 return;
990
991         if ( ctr->ctx )
992                 talloc_destroy(ctr->ctx);
993
994         ZERO_STRUCTP(ctr);
995
996         return;
997 }
998
999 /***********************************************************************
1000  **********************************************************************/
1001
1002 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1003 {
1004         if ( !ctr )
1005                 return NULL;
1006
1007         return ctr->ctx;
1008 }
1009
1010 /***********************************************************************
1011  **********************************************************************/
1012
1013 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1014 {
1015         if ( !ctr || !ctr->msg_groups )
1016                 return NULL;
1017
1018         if ( idx >= ctr->num_groups )
1019                 return NULL;
1020
1021         return &ctr->msg_groups[idx];
1022
1023 }
1024
1025 /***********************************************************************
1026  How many groups of change messages do we have ?
1027  **********************************************************************/
1028
1029 static uint32_t notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1030 {
1031         if ( !ctr )
1032                 return 0;
1033
1034         return ctr->num_groups;
1035 }
1036
1037 /***********************************************************************
1038  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1039  **********************************************************************/
1040
1041 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1042 {
1043         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1044         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1045         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1046         uint32_t                        i, new_slot;
1047
1048         if ( !ctr || !msg )
1049                 return 0;
1050
1051         /* loop over all groups looking for a matching printer name */
1052
1053         for ( i=0; i<ctr->num_groups; i++ ) {
1054                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1055                         break;
1056         }
1057
1058         /* add a new group? */
1059
1060         if ( i == ctr->num_groups ) {
1061                 ctr->num_groups++;
1062
1063                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1064                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1065                         return 0;
1066                 }
1067                 ctr->msg_groups = groups;
1068
1069                 /* clear the new entry and set the printer name */
1070
1071                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1072                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1073         }
1074
1075         /* add the change messages; 'i' is the correct index now regardless */
1076
1077         msg_grp = &ctr->msg_groups[i];
1078
1079         msg_grp->num_msgs++;
1080
1081         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1082                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1083                 return 0;
1084         }
1085         msg_grp->msgs = msg_list;
1086
1087         new_slot = msg_grp->num_msgs-1;
1088         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1089
1090         /* need to allocate own copy of data */
1091
1092         if ( msg->len != 0 )
1093                 msg_grp->msgs[new_slot].notify.data = (char *)
1094                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1095
1096         return ctr->num_groups;
1097 }
1098
1099 static void construct_info_data(struct spoolss_Notify *info_data,
1100                                 enum spoolss_NotifyType type,
1101                                 uint16_t field, int id);
1102
1103 /***********************************************************************
1104  Send a change notification message on all handles which have a call
1105  back registered
1106  **********************************************************************/
1107
1108 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1109                                   struct printer_handle *prn_hnd,
1110                                   SPOOLSS_NOTIFY_MSG *messages,
1111                                   uint32_t num_msgs,
1112                                   struct spoolss_Notify **_notifies,
1113                                   size_t *_count)
1114 {
1115         struct spoolss_Notify *notifies;
1116         SPOOLSS_NOTIFY_MSG *msg;
1117         size_t count = 0;
1118         uint32_t id;
1119         uint32_t i;
1120
1121         notifies = talloc_zero_array(mem_ctx,
1122                                      struct spoolss_Notify, num_msgs);
1123         if (!notifies) {
1124                 return ENOMEM;
1125         }
1126
1127         for (i = 0; i < num_msgs; i++) {
1128
1129                 msg = &messages[i];
1130
1131                 /* Are we monitoring this event? */
1132
1133                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1134                         continue;
1135                 }
1136
1137                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1138                            "for printer [%s]\n",
1139                            msg->type, msg->field, prn_hnd->sharename));
1140
1141                 /*
1142                  * if the is a printer notification handle and not a job
1143                  * notification type, then set the id to 0.
1144                  * Otherwise just use what was specified in the message.
1145                  *
1146                  * When registering change notification on a print server
1147                  * handle we always need to send back the id (snum) matching
1148                  * the printer for which the change took place.
1149                  * For change notify registered on a printer handle,
1150                  * this does not matter and the id should be 0.
1151                  *
1152                  * --jerry
1153                  */
1154
1155                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1156                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1157                         id = 0;
1158                 } else {
1159                         id = msg->id;
1160                 }
1161
1162                 /* Convert unix jobid to smb jobid */
1163
1164                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1165                         id = sysjob_to_jobid(msg->id);
1166
1167                         if (id == -1) {
1168                                 DEBUG(3, ("no such unix jobid %d\n",
1169                                           msg->id));
1170                                 continue;
1171                         }
1172                 }
1173
1174                 construct_info_data(&notifies[count],
1175                                     msg->type, msg->field, id);
1176
1177                 switch(msg->type) {
1178                 case PRINTER_NOTIFY_TYPE:
1179                         if (printer_notify_table[msg->field].fn) {
1180                                 printer_notify_table[msg->field].fn(msg,
1181                                                 &notifies[count], mem_ctx);
1182                         }
1183                         break;
1184
1185                 case JOB_NOTIFY_TYPE:
1186                         if (job_notify_table[msg->field].fn) {
1187                                 job_notify_table[msg->field].fn(msg,
1188                                                 &notifies[count], mem_ctx);
1189                         }
1190                         break;
1191
1192                 default:
1193                         DEBUG(5, ("Unknown notification type %d\n",
1194                                   msg->type));
1195                         continue;
1196                 }
1197
1198                 count++;
1199         }
1200
1201         *_notifies = notifies;
1202         *_count = count;
1203
1204         return 0;
1205 }
1206
1207 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1208                                 struct printer_handle *prn_hnd,
1209                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1210 {
1211         struct spoolss_Notify *notifies;
1212         size_t count = 0;
1213         union spoolss_ReplyPrinterInfo info;
1214         struct spoolss_NotifyInfo info0;
1215         uint32_t reply_result;
1216         NTSTATUS status;
1217         WERROR werr;
1218         int ret;
1219
1220         /* Is there notification on this handle? */
1221         if (prn_hnd->notify.cli_chan == NULL ||
1222             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1223             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1224             prn_hnd->notify.cli_chan->active_connections == 0) {
1225                 return 0;
1226         }
1227
1228         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1229                    prn_hnd->servername, prn_hnd->sharename));
1230
1231         /* For this printer? Print servers always receive notifications. */
1232         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1233             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1234                 return 0;
1235         }
1236
1237         DEBUG(10,("Our printer\n"));
1238
1239         /* build the array of change notifications */
1240         ret = build_notify2_messages(mem_ctx, prn_hnd,
1241                                      msg_group->msgs,
1242                                      msg_group->num_msgs,
1243                                      &notifies, &count);
1244         if (ret) {
1245                 return ret;
1246         }
1247
1248         info0.version   = 0x2;
1249         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1250         info0.count     = count;
1251         info0.notifies  = notifies;
1252
1253         info.info0 = &info0;
1254
1255         status = dcerpc_spoolss_RouterReplyPrinterEx(
1256                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1257                                 mem_ctx,
1258                                 &prn_hnd->notify.cli_hnd,
1259                                 prn_hnd->notify.change, /* color */
1260                                 prn_hnd->notify.flags,
1261                                 &reply_result,
1262                                 0, /* reply_type, must be 0 */
1263                                 info, &werr);
1264         if (!NT_STATUS_IS_OK(status)) {
1265                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1266                           "failed: %s\n",
1267                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1268                           nt_errstr(status)));
1269                 werr = ntstatus_to_werror(status);
1270         } else if (!W_ERROR_IS_OK(werr)) {
1271                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1272                           "failed: %s\n",
1273                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1274                           win_errstr(werr)));
1275         }
1276         switch (reply_result) {
1277         case 0:
1278                 break;
1279         case PRINTER_NOTIFY_INFO_DISCARDED:
1280         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1281         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1282                 break;
1283         default:
1284                 break;
1285         }
1286
1287         return 0;
1288 }
1289
1290 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1291 {
1292         struct printer_handle    *p;
1293         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1294         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1295         int ret;
1296
1297         if ( !msg_group ) {
1298                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1299                 return;
1300         }
1301
1302         if (!msg_group->msgs) {
1303                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1304                 return;
1305         }
1306
1307         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1308
1309         /* loop over all printers */
1310
1311         for (p = printers_list; p; p = p->next) {
1312                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1313                 if (ret) {
1314                         goto done;
1315                 }
1316         }
1317
1318 done:
1319         DEBUG(8,("send_notify2_changes: Exit...\n"));
1320         return;
1321 }
1322
1323 /***********************************************************************
1324  **********************************************************************/
1325
1326 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1327 {
1328
1329         uint32_t tv_sec, tv_usec;
1330         size_t offset = 0;
1331
1332         /* Unpack message */
1333
1334         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1335                              msg->printer);
1336
1337         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1338                                 &tv_sec, &tv_usec,
1339                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1340
1341         if (msg->len == 0)
1342                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1343                            &msg->notify.value[0], &msg->notify.value[1]);
1344         else
1345                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1346                            &msg->len, &msg->notify.data);
1347
1348         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1349                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1350
1351         tv->tv_sec = tv_sec;
1352         tv->tv_usec = tv_usec;
1353
1354         if (msg->len == 0)
1355                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1356                           msg->notify.value[1]));
1357         else
1358                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1359
1360         return true;
1361 }
1362
1363 /********************************************************************
1364  Receive a notify2 message list
1365  ********************************************************************/
1366
1367 static void receive_notify2_message_list(struct messaging_context *msg,
1368                                          void *private_data,
1369                                          uint32_t msg_type,
1370                                          struct server_id server_id,
1371                                          DATA_BLOB *data)
1372 {
1373         size_t                  msg_count, i, num_groups;
1374         char                    *buf = (char *)data->data;
1375         char                    *msg_ptr;
1376         size_t                  msg_len;
1377         SPOOLSS_NOTIFY_MSG      notify;
1378         SPOOLSS_NOTIFY_MSG_CTR  messages;
1379
1380         if (data->length < 4) {
1381                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1382                 return;
1383         }
1384
1385         msg_count = IVAL(buf, 0);
1386         msg_ptr = buf + 4;
1387
1388         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1389
1390         if (msg_count == 0) {
1391                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1392                 return;
1393         }
1394
1395         /* initialize the container */
1396
1397         ZERO_STRUCT( messages );
1398         notify_msg_ctr_init( &messages );
1399
1400         /*
1401          * build message groups for each printer identified
1402          * in a change_notify msg.  Remember that a PCN message
1403          * includes the handle returned for the srv_spoolss_replyopenprinter()
1404          * call.  Therefore messages are grouped according to printer handle.
1405          */
1406
1407         for ( i=0; i<msg_count; i++ ) {
1408                 struct timeval msg_tv;
1409
1410                 if (msg_ptr + 4 - buf > data->length) {
1411                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1412                         return;
1413                 }
1414
1415                 msg_len = IVAL(msg_ptr,0);
1416                 msg_ptr += 4;
1417
1418                 if (msg_ptr + msg_len - buf > data->length) {
1419                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1420                         return;
1421                 }
1422
1423                 /* unpack messages */
1424
1425                 ZERO_STRUCT( notify );
1426                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1427                 msg_ptr += msg_len;
1428
1429                 /* add to correct list in container */
1430
1431                 notify_msg_ctr_addmsg( &messages, &notify );
1432
1433                 /* free memory that might have been allocated by notify2_unpack_msg() */
1434
1435                 if ( notify.len != 0 )
1436                         SAFE_FREE( notify.notify.data );
1437         }
1438
1439         /* process each group of messages */
1440
1441         num_groups = notify_msg_ctr_numgroups( &messages );
1442         for ( i=0; i<num_groups; i++ )
1443                 send_notify2_changes( &messages, i );
1444
1445
1446         /* cleanup */
1447
1448         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1449                 (uint32_t)msg_count ));
1450
1451         notify_msg_ctr_destroy( &messages );
1452
1453         return;
1454 }
1455
1456 /********************************************************************
1457  Send a message to ourself about new driver being installed
1458  so we can upgrade the information for each printer bound to this
1459  driver
1460  ********************************************************************/
1461
1462 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1463                                             struct messaging_context *msg_ctx)
1464 {
1465         int len = strlen(drivername);
1466
1467         if (!len)
1468                 return false;
1469
1470         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1471                 drivername));
1472
1473         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1474                            MSG_PRINTER_DRVUPGRADE,
1475                            (const uint8_t *)drivername, len+1);
1476
1477         return true;
1478 }
1479
1480 void srv_spoolss_cleanup(void)
1481 {
1482         struct printer_session_counter *session_counter;
1483
1484         for (session_counter = counter_list;
1485              session_counter != NULL;
1486              session_counter = counter_list) {
1487                 DLIST_REMOVE(counter_list, session_counter);
1488                 TALLOC_FREE(session_counter);
1489         }
1490 }
1491
1492 /**********************************************************************
1493  callback to receive a MSG_PRINTER_DRVUPGRADE message and iterate
1494  over all printers, upgrading ones as necessary
1495  This is now *ONLY* called inside the background lpq updater. JRA.
1496  **********************************************************************/
1497
1498 void do_drv_upgrade_printer(struct messaging_context *msg,
1499                             void *private_data,
1500                             uint32_t msg_type,
1501                             struct server_id server_id,
1502                             DATA_BLOB *data)
1503 {
1504         TALLOC_CTX *tmp_ctx;
1505         const struct auth_session_info *session_info = get_session_info_system();
1506         struct spoolss_PrinterInfo2 *pinfo2;
1507         WERROR result;
1508         const char *drivername;
1509         int snum;
1510         int n_services = lp_numservices();
1511         struct dcerpc_binding_handle *b = NULL;
1512
1513         tmp_ctx = talloc_new(NULL);
1514         if (!tmp_ctx) return;
1515
1516         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1517         if (!drivername) {
1518                 DEBUG(0, ("do_drv_upgrade_printer: Out of memory ?!\n"));
1519                 goto done;
1520         }
1521
1522         DEBUG(10, ("do_drv_upgrade_printer: "
1523                    "Got message for new driver [%s]\n", drivername));
1524
1525         /* Iterate the printer list */
1526
1527         for (snum = 0; snum < n_services; snum++) {
1528                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1529                         continue;
1530                 }
1531
1532                 /* ignore [printers] share */
1533                 if (strequal(lp_const_servicename(snum), "printers")) {
1534                         continue;
1535                 }
1536
1537                 if (b == NULL) {
1538                         result = winreg_printer_binding_handle(tmp_ctx,
1539                                                                session_info,
1540                                                                msg,
1541                                                                &b);
1542                         if (!W_ERROR_IS_OK(result)) {
1543                                 break;
1544                         }
1545                 }
1546
1547                 result = winreg_get_printer(tmp_ctx, b,
1548                                             lp_const_servicename(snum),
1549                                             &pinfo2);
1550
1551                 if (!W_ERROR_IS_OK(result)) {
1552                         continue;
1553                 }
1554
1555                 if (!pinfo2->drivername) {
1556                         continue;
1557                 }
1558
1559                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1560                         continue;
1561                 }
1562
1563                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1564
1565                 /* all we care about currently is the change_id */
1566                 result = winreg_printer_update_changeid(tmp_ctx, b,
1567                                                         pinfo2->printername);
1568
1569                 if (!W_ERROR_IS_OK(result)) {
1570                         DEBUG(3, ("do_drv_upgrade_printer: "
1571                                   "Failed to update changeid [%s]\n",
1572                                   win_errstr(result)));
1573                 }
1574         }
1575
1576         /* all done */
1577 done:
1578         talloc_free(tmp_ctx);
1579 }
1580
1581 /********************************************************************
1582  Update the cache for all printq's with a registered client
1583  connection
1584  ********************************************************************/
1585
1586 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1587 {
1588         struct printer_handle *printer = printers_list;
1589         int snum;
1590
1591         /* loop through all printers and update the cache where
1592            a client is connected */
1593         while (printer) {
1594                 if ((printer->printer_type == SPLHND_PRINTER) &&
1595                     ((printer->notify.cli_chan != NULL) &&
1596                      (printer->notify.cli_chan->active_connections > 0))) {
1597                         snum = print_queue_snum(printer->sharename);
1598                         print_queue_status(msg_ctx, snum, NULL, NULL);
1599                 }
1600
1601                 printer = printer->next;
1602         }
1603
1604         return;
1605 }
1606
1607 /****************************************************************
1608  _spoolss_OpenPrinter
1609 ****************************************************************/
1610
1611 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1612                             struct spoolss_OpenPrinter *r)
1613 {
1614         struct spoolss_OpenPrinterEx e;
1615         struct spoolss_UserLevel1 level1;
1616         WERROR werr;
1617
1618         ZERO_STRUCT(level1);
1619
1620         e.in.printername        = r->in.printername;
1621         e.in.datatype           = r->in.datatype;
1622         e.in.devmode_ctr        = r->in.devmode_ctr;
1623         e.in.access_mask        = r->in.access_mask;
1624         e.in.userlevel_ctr.level                = 1;
1625         e.in.userlevel_ctr.user_info.level1     = &level1;
1626
1627         e.out.handle            = r->out.handle;
1628
1629         werr = _spoolss_OpenPrinterEx(p, &e);
1630
1631         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1632                 /* OpenPrinterEx returns this for a bad
1633                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1634                  * instead.
1635                  */
1636                 werr = WERR_INVALID_PRINTER_NAME;
1637         }
1638
1639         return werr;
1640 }
1641
1642 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1643                               struct spoolss_DeviceMode *orig,
1644                               struct spoolss_DeviceMode **dest)
1645 {
1646         struct spoolss_DeviceMode *dm;
1647
1648         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1649         if (!dm) {
1650                 return WERR_NOT_ENOUGH_MEMORY;
1651         }
1652
1653         /* copy all values, then duplicate strings and structs */
1654         *dm = *orig;
1655
1656         dm->devicename = talloc_strdup(dm, orig->devicename);
1657         if (!dm->devicename) {
1658                 return WERR_NOT_ENOUGH_MEMORY;
1659         }
1660         dm->formname = talloc_strdup(dm, orig->formname);
1661         if (!dm->formname) {
1662                 return WERR_NOT_ENOUGH_MEMORY;
1663         }
1664         if (orig->driverextra_data.data) {
1665                 dm->driverextra_data.data =
1666                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1667                                         orig->driverextra_data.length);
1668                 if (!dm->driverextra_data.data) {
1669                         return WERR_NOT_ENOUGH_MEMORY;
1670                 }
1671         }
1672
1673         *dest = dm;
1674         return WERR_OK;
1675 }
1676
1677 /****************************************************************
1678  _spoolss_OpenPrinterEx
1679 ****************************************************************/
1680
1681 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1682                               struct spoolss_OpenPrinterEx *r)
1683 {
1684         struct dcesrv_call_state *dce_call = p->dce_call;
1685         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
1686         const struct tsocket_address *remote_address =
1687                 dcesrv_connection_get_remote_address(dcesrv_conn);
1688         struct auth_session_info *session_info =
1689                 dcesrv_call_session_info(dce_call);
1690         int snum;
1691         char *raddr;
1692         char *rhost;
1693         struct printer_handle *Printer=NULL;
1694         WERROR result;
1695         int rc;
1696
1697         if (!r->in.printername) {
1698                 return WERR_INVALID_PARAMETER;
1699         }
1700
1701         if (!*r->in.printername) {
1702                 return WERR_INVALID_PARAMETER;
1703         }
1704
1705         if (r->in.userlevel_ctr.level > 3) {
1706                 return WERR_INVALID_PARAMETER;
1707         }
1708         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1709             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1710             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1711                 return WERR_INVALID_PARAMETER;
1712         }
1713
1714         /*
1715          * The printcap printer share inventory is updated on client
1716          * enumeration. For clients that do not perform enumeration prior to
1717          * access, such as cupssmbadd, we reinitialise the printer share
1718          * inventory on open as well.
1719          */
1720         become_root();
1721         delete_and_reload_printers();
1722         unbecome_root();
1723
1724         /* some sanity check because you can open a printer or a print server */
1725         /* aka: \\server\printer or \\server */
1726
1727         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1728
1729         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1730         if (!W_ERROR_IS_OK(result)) {
1731                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1732                         "for printer %s\n", r->in.printername));
1733                 ZERO_STRUCTP(r->out.handle);
1734                 return result;
1735         }
1736
1737         Printer = find_printer_index_by_hnd(p, r->out.handle);
1738         if ( !Printer ) {
1739                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1740                         "handle we created for printer %s\n", r->in.printername));
1741                 close_printer_handle(p, r->out.handle);
1742                 ZERO_STRUCTP(r->out.handle);
1743                 return WERR_INVALID_PARAMETER;
1744         }
1745
1746         /*
1747          * First case: the user is opening the print server:
1748          *
1749          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1750          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1751          *
1752          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1753          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1754          * or if the user is listed in the smb.conf printer admin parameter.
1755          *
1756          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1757          * client view printer folder, but does not show the MSAPW.
1758          *
1759          * Note: this test needs code to check access rights here too. Jeremy
1760          * could you look at this?
1761          *
1762          * Second case: the user is opening a printer:
1763          * NT doesn't let us connect to a printer if the connecting user
1764          * doesn't have print permission.
1765          *
1766          * Third case: user is opening a Port Monitor
1767          * access checks same as opening a handle to the print server.
1768          */
1769
1770         switch (Printer->printer_type )
1771         {
1772         case SPLHND_SERVER:
1773         case SPLHND_PORTMON_TCP:
1774         case SPLHND_PORTMON_LOCAL:
1775                 /* Printserver handles use global struct... */
1776
1777                 snum = -1;
1778
1779                 if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1780                         r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1781                         r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1782                 }
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 ((session_info->unix_token->uid != sec_initial_uid()) &&
1816                             !security_token_has_privilege(
1817                                     session_info->security_token,
1818                                     SEC_PRIV_PRINT_OPERATOR) &&
1819                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1820                                                 session_info->security_token)) {
1821                                 close_printer_handle(p, r->out.handle);
1822                                 ZERO_STRUCTP(r->out.handle);
1823                                 DEBUG(3,("access DENIED as user is not root, "
1824                                         "has no printoperator privilege and is "
1825                                         "not a member of the printoperator builtin group\n"));
1826                                 return WERR_ACCESS_DENIED;
1827                         }
1828
1829                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1830                 }
1831                 else
1832                 {
1833                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1834                 }
1835
1836                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1837                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1838
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_INVALID_HANDLE;
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(remote_address,
1875                                                          p->mem_ctx);
1876                 if (raddr == NULL) {
1877                         return WERR_NOT_ENOUGH_MEMORY;
1878                 }
1879
1880                 rc = get_remote_hostname(remote_address,
1881                                          &rhost,
1882                                          p->mem_ctx);
1883                 if (rc < 0) {
1884                         return WERR_NOT_ENOUGH_MEMORY;
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(session_info->unix_info->unix_name,
1898                                    session_info->info->domain_name,
1899                                    session_info->security_token, snum) ||
1900                     !W_ERROR_IS_OK(print_access_check(session_info,
1901                                                       p->msg_ctx,
1902                                                       snum,
1903                                                       r->in.access_mask))) {
1904                         DEBUG(3, ("access DENIED for printer open\n"));
1905                         close_printer_handle(p, r->out.handle);
1906                         ZERO_STRUCTP(r->out.handle);
1907                         return WERR_ACCESS_DENIED;
1908                 }
1909
1910                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1911                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1912                         close_printer_handle(p, r->out.handle);
1913                         ZERO_STRUCTP(r->out.handle);
1914                         return WERR_ACCESS_DENIED;
1915                 }
1916
1917                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1918                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1919                 else
1920                         r->in.access_mask = PRINTER_ACCESS_USE;
1921
1922                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1923                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1924
1925                 winreg_create_printer_internal(p->mem_ctx,
1926                                       get_session_info_system(),
1927                                       p->msg_ctx,
1928                                       lp_const_servicename(snum));
1929
1930                 break;
1931
1932         default:
1933                 /* sanity check to prevent programmer error */
1934                 ZERO_STRUCTP(r->out.handle);
1935                 return WERR_INVALID_HANDLE;
1936         }
1937
1938         Printer->access_granted = r->in.access_mask;
1939
1940         /*
1941          * If the client sent a devmode in the OpenPrinter() call, then
1942          * save it here in case we get a job submission on this handle
1943          */
1944
1945          if ((Printer->printer_type != SPLHND_SERVER)
1946           && (r->in.devmode_ctr.devmode != NULL)) {
1947                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1948                                 &Printer->devmode);
1949          }
1950
1951         return WERR_OK;
1952 }
1953
1954 /****************************************************************
1955  _spoolss_ClosePrinter
1956 ****************************************************************/
1957
1958 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1959                              struct spoolss_ClosePrinter *r)
1960 {
1961         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1962
1963         if (Printer && Printer->document_started) {
1964                 struct spoolss_EndDocPrinter e;
1965
1966                 e.in.handle = r->in.handle;
1967
1968                 _spoolss_EndDocPrinter(p, &e);
1969         }
1970
1971         if (!close_printer_handle(p, r->in.handle))
1972                 return WERR_INVALID_HANDLE;
1973
1974         /* clear the returned printer handle.  Observed behavior
1975            from Win2k server.  Don't think this really matters.
1976            Previous code just copied the value of the closed
1977            handle.    --jerry */
1978
1979         ZERO_STRUCTP(r->out.handle);
1980
1981         return WERR_OK;
1982 }
1983
1984 /****************************************************************
1985  _spoolss_DeletePrinter
1986 ****************************************************************/
1987
1988 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1989                               struct spoolss_DeletePrinter *r)
1990 {
1991         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1992         WERROR result;
1993         int snum;
1994
1995         if (Printer && Printer->document_started) {
1996                 struct spoolss_EndDocPrinter e;
1997
1998                 e.in.handle = r->in.handle;
1999
2000                 _spoolss_EndDocPrinter(p, &e);
2001         }
2002
2003         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2004                 winreg_delete_printer_key_internal(p->mem_ctx,
2005                                           get_session_info_system(),
2006                                           p->msg_ctx,
2007                                           lp_const_servicename(snum),
2008                                           "");
2009         }
2010
2011         result = delete_printer_handle(p, r->in.handle);
2012
2013         return result;
2014 }
2015
2016 /*******************************************************************
2017  * static function to lookup the version id corresponding to an
2018  * long architecture string
2019  ******************************************************************/
2020
2021 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2022                                    SPOOLSS_DRIVER_VERSION_NT35,
2023                                    SPOOLSS_DRIVER_VERSION_NT4,
2024                                    SPOOLSS_DRIVER_VERSION_200X,
2025                                    -1};
2026
2027 static int get_version_id(const char *arch)
2028 {
2029         int i;
2030
2031         for (i=0; archi_table[i].long_archi != NULL; i++)
2032         {
2033                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2034                         return (archi_table[i].version);
2035         }
2036
2037         return -1;
2038 }
2039
2040 /****************************************************************
2041  _spoolss_DeletePrinterDriver
2042 ****************************************************************/
2043
2044 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2045                                     struct spoolss_DeletePrinterDriver *r)
2046 {
2047
2048         struct dcesrv_call_state *dce_call = p->dce_call;
2049         struct auth_session_info *session_info =
2050                 dcesrv_call_session_info(dce_call);
2051         struct spoolss_DriverInfo8 *info = NULL;
2052         int                             version;
2053         WERROR                          status;
2054         struct dcerpc_binding_handle *b;
2055         TALLOC_CTX *tmp_ctx = NULL;
2056         int i;
2057         bool found;
2058
2059         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2060            and not a printer admin, then fail */
2061
2062         if ((session_info->unix_token->uid != sec_initial_uid()) &&
2063             !security_token_has_privilege(session_info->security_token,
2064                                           SEC_PRIV_PRINT_OPERATOR)) {
2065                 return WERR_ACCESS_DENIED;
2066         }
2067
2068         if (r->in.architecture == NULL || r->in.driver == NULL) {
2069                 return WERR_INVALID_ENVIRONMENT;
2070         }
2071
2072         /* check that we have a valid driver name first */
2073
2074         if ((version = get_version_id(r->in.architecture)) == -1) {
2075                 return WERR_INVALID_ENVIRONMENT;
2076         }
2077
2078         tmp_ctx = talloc_new(p->mem_ctx);
2079         if (!tmp_ctx) {
2080                 return WERR_NOT_ENOUGH_MEMORY;
2081         }
2082
2083         status = winreg_printer_binding_handle(tmp_ctx,
2084                                                get_session_info_system(),
2085                                                p->msg_ctx,
2086                                                &b);
2087         if (!W_ERROR_IS_OK(status)) {
2088                 goto done;
2089         }
2090
2091         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2092                 status = winreg_get_driver(tmp_ctx, b,
2093                                            r->in.architecture, r->in.driver,
2094                                            drv_cversion[i], &info);
2095                 if (!W_ERROR_IS_OK(status)) {
2096                         DEBUG(5, ("skipping del of driver with version %d\n",
2097                                   drv_cversion[i]));
2098                         continue;
2099                 }
2100                 found = true;
2101
2102                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2103                         status = WERR_PRINTER_DRIVER_IN_USE;
2104                         goto done;
2105                 }
2106
2107                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2108                 if (!W_ERROR_IS_OK(status)) {
2109                         DEBUG(0, ("failed del of driver with version %d\n",
2110                                   drv_cversion[i]));
2111                         goto done;
2112                 }
2113         }
2114         if (found == false) {
2115                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2116                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2117         } else {
2118                 status = WERR_OK;
2119         }
2120
2121 done:
2122         talloc_free(tmp_ctx);
2123
2124         return status;
2125 }
2126
2127 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2128                                   struct pipes_struct *p,
2129                                   struct spoolss_DeletePrinterDriverEx *r,
2130                                   struct dcerpc_binding_handle *b,
2131                                   struct spoolss_DriverInfo8 *info)
2132 {
2133         struct dcesrv_call_state *dce_call = p->dce_call;
2134         struct auth_session_info *session_info =
2135                 dcesrv_call_session_info(dce_call);
2136         WERROR status;
2137         bool delete_files;
2138
2139         if (printer_driver_in_use(mem_ctx, b, info)) {
2140                 status = WERR_PRINTER_DRIVER_IN_USE;
2141                 goto done;
2142         }
2143
2144         /*
2145          * we have a couple of cases to consider.
2146          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2147          *     then the delete should fail if **any** files overlap with
2148          *     other drivers
2149          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2150          *     non-overlapping files
2151          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2152          *     are set, then do not delete any files
2153          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2154          */
2155
2156         delete_files = r->in.delete_flags
2157                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2158
2159
2160         if (delete_files) {
2161                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2162                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2163                         status = WERR_PRINTER_DRIVER_IN_USE;
2164                         goto done;
2165                 }
2166                 /*
2167                  * printer_driver_files_in_use() has trimmed overlapping files
2168                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2169                  */
2170         }
2171
2172
2173         status = winreg_del_driver(mem_ctx, b, info, info->version);
2174         if (!W_ERROR_IS_OK(status)) {
2175                 goto done;
2176         }
2177
2178         /*
2179          * now delete any associated files if delete_files is
2180          * true. Even if this part fails, we return success
2181          * because the driver does not exist any more
2182          */
2183         if (delete_files) {
2184                 delete_driver_files(session_info, info);
2185         }
2186
2187 done:
2188         return status;
2189 }
2190
2191 /****************************************************************
2192  _spoolss_DeletePrinterDriverEx
2193 ****************************************************************/
2194
2195 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2196                                       struct spoolss_DeletePrinterDriverEx *r)
2197 {
2198         struct dcesrv_call_state *dce_call = p->dce_call;
2199         struct auth_session_info *session_info =
2200                 dcesrv_call_session_info(dce_call);
2201         struct spoolss_DriverInfo8 *info = NULL;
2202         WERROR                          status;
2203         struct dcerpc_binding_handle *b;
2204         TALLOC_CTX *tmp_ctx = NULL;
2205         int i;
2206         bool found;
2207
2208         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2209            and not a printer admin, then fail */
2210
2211         if ((session_info->unix_token->uid != sec_initial_uid()) &&
2212             !security_token_has_privilege(session_info->security_token,
2213                                           SEC_PRIV_PRINT_OPERATOR)) {
2214                 return WERR_ACCESS_DENIED;
2215         }
2216
2217         if (r->in.architecture == NULL || r->in.driver == NULL) {
2218                 return WERR_INVALID_ENVIRONMENT;
2219         }
2220
2221         /* check that we have a valid driver name first */
2222         if (get_version_id(r->in.architecture) == -1) {
2223                 /* this is what NT returns */
2224                 return WERR_INVALID_ENVIRONMENT;
2225         }
2226
2227         tmp_ctx = talloc_new(p->mem_ctx);
2228         if (!tmp_ctx) {
2229                 return WERR_NOT_ENOUGH_MEMORY;
2230         }
2231
2232         status = winreg_printer_binding_handle(tmp_ctx,
2233                                                get_session_info_system(),
2234                                                p->msg_ctx,
2235                                                &b);
2236         if (!W_ERROR_IS_OK(status)) {
2237                 goto done;
2238         }
2239
2240         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2241                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2242                  && (drv_cversion[i] != r->in.version)) {
2243                         continue;
2244                 }
2245
2246                 /* check if a driver with this version exists before delete */
2247                 status = winreg_get_driver(tmp_ctx, b,
2248                                            r->in.architecture, r->in.driver,
2249                                            drv_cversion[i], &info);
2250                 if (!W_ERROR_IS_OK(status)) {
2251                         DEBUG(5, ("skipping del of driver with version %d\n",
2252                                   drv_cversion[i]));
2253                         continue;
2254                 }
2255                 found = true;
2256
2257                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2258                 if (!W_ERROR_IS_OK(status)) {
2259                         DEBUG(0, ("failed to delete driver with version %d\n",
2260                                   drv_cversion[i]));
2261                         goto done;
2262                 }
2263         }
2264         if (found == false) {
2265                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2266                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2267         } else {
2268                 status = WERR_OK;
2269         }
2270
2271 done:
2272         talloc_free(tmp_ctx);
2273         return status;
2274 }
2275
2276
2277 /********************************************************************
2278  GetPrinterData on a printer server Handle.
2279 ********************************************************************/
2280
2281 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2282                                             const char *value,
2283                                             enum winreg_Type *type,
2284                                             union spoolss_PrinterData *data)
2285 {
2286         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2287
2288         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2289                 *type = REG_DWORD;
2290                 SIVAL(&data->value, 0, 0x00);
2291                 return WERR_OK;
2292         }
2293
2294         if (!strcasecmp_m(value, "BeepEnabled")) {
2295                 *type = REG_DWORD;
2296                 SIVAL(&data->value, 0, 0x00);
2297                 return WERR_OK;
2298         }
2299
2300         if (!strcasecmp_m(value, "EventLog")) {
2301                 *type = REG_DWORD;
2302                 /* formally was 0x1b */
2303                 SIVAL(&data->value, 0, 0x00);
2304                 return WERR_OK;
2305         }
2306
2307         if (!strcasecmp_m(value, "NetPopup")) {
2308                 *type = REG_DWORD;
2309                 SIVAL(&data->value, 0, 0x00);
2310                 return WERR_OK;
2311         }
2312
2313         if (!strcasecmp_m(value, "MajorVersion")) {
2314                 *type = REG_DWORD;
2315
2316                 /* Windows NT 4.0 seems to not allow uploading of drivers
2317                    to a server that reports 0x3 as the MajorVersion.
2318                    need to investigate more how Win2k gets around this .
2319                    -- jerry */
2320
2321                 if (RA_WINNT == get_remote_arch()) {
2322                         SIVAL(&data->value, 0, 0x02);
2323                 } else {
2324                         SIVAL(&data->value, 0, 0x03);
2325                 }
2326
2327                 return WERR_OK;
2328         }
2329
2330         if (!strcasecmp_m(value, "MinorVersion")) {
2331                 *type = REG_DWORD;
2332                 SIVAL(&data->value, 0, 0x00);
2333                 return WERR_OK;
2334         }
2335
2336         /* REG_BINARY
2337          *  uint32_t size        = 0x114
2338          *  uint32_t major       = 5
2339          *  uint32_t minor       = [0|1]
2340          *  uint32_t build       = [2195|2600]
2341          *  extra unicode string = e.g. "Service Pack 3"
2342          */
2343         if (!strcasecmp_m(value, "OSVersion")) {
2344                 DATA_BLOB blob;
2345                 enum ndr_err_code ndr_err;
2346                 struct spoolss_OSVersion os;
2347
2348                 /*
2349                  * Set the default OSVersion to:
2350                  *
2351                  *     Windows Server 2003R2 SP2 (5.2.3790)
2352                  *
2353                  * used to be Windows 2000 (5.0.2195)
2354                  */
2355                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
2356                                                       "spoolss", "os_major",
2357                                                       GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
2358                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
2359                                                       "spoolss", "os_minor",
2360                                                       GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
2361                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
2362                                                       "spoolss", "os_build",
2363                                                       GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
2364                 os.extra_string         = "";   /* leave extra string empty */
2365
2366                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2367                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2368                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2369                         return WERR_GEN_FAILURE;
2370                 }
2371
2372                 if (DEBUGLEVEL >= 10) {
2373                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2374                 }
2375
2376                 *type = REG_BINARY;
2377                 data->binary = blob;
2378
2379                 return WERR_OK;
2380         }
2381
2382
2383         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2384                 *type = REG_SZ;
2385
2386                 data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
2387                 W_ERROR_HAVE_NO_MEMORY(data->string);
2388
2389                 return WERR_OK;
2390         }
2391
2392         if (!strcasecmp_m(value, "Architecture")) {
2393                 *type = REG_SZ;
2394                 data->string = talloc_strdup(mem_ctx,
2395                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
2396                 W_ERROR_HAVE_NO_MEMORY(data->string);
2397
2398                 return WERR_OK;
2399         }
2400
2401         if (!strcasecmp_m(value, "DsPresent")) {
2402                 *type = REG_DWORD;
2403
2404                 /* only show the publish check box if we are a
2405                    member of a AD domain */
2406
2407                 if (lp_security() == SEC_ADS) {
2408                         SIVAL(&data->value, 0, 0x01);
2409                 } else {
2410                         SIVAL(&data->value, 0, 0x00);
2411                 }
2412                 return WERR_OK;
2413         }
2414
2415         if (!strcasecmp_m(value, "DNSMachineName")) {
2416                 const char *hostname = get_mydnsfullname();
2417
2418                 if (!hostname) {
2419                         return WERR_FILE_NOT_FOUND;
2420                 }
2421
2422                 *type = REG_SZ;
2423                 data->string = talloc_strdup(mem_ctx, hostname);
2424                 W_ERROR_HAVE_NO_MEMORY(data->string);
2425
2426                 return WERR_OK;
2427         }
2428
2429         *type = REG_NONE;
2430
2431         return WERR_INVALID_PARAMETER;
2432 }
2433
2434 /****************************************************************
2435  _spoolss_GetPrinterData
2436 ****************************************************************/
2437
2438 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2439                                struct spoolss_GetPrinterData *r)
2440 {
2441         struct spoolss_GetPrinterDataEx r2;
2442
2443         r2.in.handle            = r->in.handle;
2444         r2.in.key_name          = "PrinterDriverData";
2445         r2.in.value_name        = r->in.value_name;
2446         r2.in.offered           = r->in.offered;
2447         r2.out.type             = r->out.type;
2448         r2.out.data             = r->out.data;
2449         r2.out.needed           = r->out.needed;
2450
2451         return _spoolss_GetPrinterDataEx(p, &r2);
2452 }
2453
2454 /*********************************************************
2455  Connect to the client machine.
2456 **********************************************************/
2457
2458 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2459                                       struct sockaddr_storage *client_ss, const char *remote_machine)
2460 {
2461         NTSTATUS ret;
2462         struct sockaddr_storage rm_addr;
2463         char addr[INET6_ADDRSTRLEN];
2464         struct cli_credentials *anon_creds = NULL;
2465
2466         if ( is_zero_addr(client_ss) ) {
2467                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2468                         remote_machine));
2469                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2470                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2471                         return false;
2472                 }
2473                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2474         } else {
2475                 rm_addr = *client_ss;
2476                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2477                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2478                         addr));
2479         }
2480
2481         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2482                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2483                         addr));
2484                 return false;
2485         }
2486
2487         anon_creds = cli_credentials_init_anon(NULL);
2488         if (anon_creds == NULL) {
2489                 DBG_ERR("cli_credentials_init_anon() failed\n");
2490                 return false;
2491         }
2492
2493         /* setup the connection */
2494         ret = cli_full_connection_creds( pp_cli, lp_netbios_name(), remote_machine,
2495                 &rm_addr, 0, "IPC$", "IPC",
2496                 anon_creds,
2497                 CLI_FULL_CONNECTION_IPC);
2498         TALLOC_FREE(anon_creds);
2499         if ( !NT_STATUS_IS_OK( ret ) ) {
2500                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2501                         remote_machine ));
2502                 return false;
2503         }
2504
2505         if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
2506                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2507                 cli_shutdown(*pp_cli);
2508                 return false;
2509         }
2510
2511         /*
2512          * Ok - we have an anonymous connection to the IPC$ share.
2513          * Now start the NT Domain stuff :-).
2514          */
2515
2516         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2517         if (!NT_STATUS_IS_OK(ret)) {
2518                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2519                         remote_machine, nt_errstr(ret)));
2520                 cli_shutdown(*pp_cli);
2521                 return false;
2522         }
2523
2524         return true;
2525 }
2526
2527 /***************************************************************************
2528  Connect to the client.
2529 ****************************************************************************/
2530
2531 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2532                                         uint32_t localprinter,
2533                                         enum winreg_Type type,
2534                                         struct policy_handle *handle,
2535                                         struct notify_back_channel **_chan,
2536                                         struct sockaddr_storage *client_ss,
2537                                         struct messaging_context *msg_ctx)
2538 {
2539         WERROR result;
2540         NTSTATUS status;
2541         struct notify_back_channel *chan;
2542
2543         for (chan = back_channels; chan; chan = chan->next) {
2544                 if (memcmp(&chan->client_address, client_ss,
2545                            sizeof(struct sockaddr_storage)) == 0) {
2546                         break;
2547                 }
2548         }
2549
2550         /*
2551          * If it's the first connection, contact the client
2552          * and connect to the IPC$ share anonymously
2553          */
2554         if (!chan) {
2555                 fstring unix_printer;
2556
2557                 /* the +2 is to strip the leading 2 backslashes */
2558                 fstrcpy(unix_printer, printer + 2);
2559
2560                 chan = talloc_zero(NULL, struct notify_back_channel);
2561                 if (!chan) {
2562                         return false;
2563                 }
2564                 chan->client_address = *client_ss;
2565
2566                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2567                         TALLOC_FREE(chan);
2568                         return false;
2569                 }
2570
2571                 DLIST_ADD(back_channels, chan);
2572
2573                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2574                                    receive_notify2_message_list);
2575         }
2576
2577         if (chan->cli_pipe == NULL ||
2578             chan->cli_pipe->binding_handle == NULL) {
2579                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2580                         "NULL %s for printer %s\n",
2581                         chan->cli_pipe == NULL ?
2582                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2583                         printer));
2584                 return false;
2585         }
2586
2587         /*
2588          * Tell the specific printing tdb we want messages for this printer
2589          * by registering our PID.
2590          */
2591
2592         if (!print_notify_register_pid(snum)) {
2593                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2594                           printer));
2595         }
2596
2597         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2598                                                  talloc_tos(),
2599                                                  printer,
2600                                                  localprinter,
2601                                                  type,
2602                                                  0,
2603                                                  NULL,
2604                                                  handle,
2605                                                  &result);
2606         if (!NT_STATUS_IS_OK(status)) {
2607                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2608                 result = ntstatus_to_werror(status);
2609         } else if (!W_ERROR_IS_OK(result)) {
2610                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2611         }
2612
2613         chan->active_connections++;
2614         *_chan = chan;
2615
2616         return (W_ERROR_IS_OK(result));
2617 }
2618
2619 /****************************************************************
2620  ****************************************************************/
2621
2622 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2623                                                              const struct spoolss_NotifyOption *r)
2624 {
2625         struct spoolss_NotifyOption *option;
2626         uint32_t i,k;
2627
2628         if (!r) {
2629                 return NULL;
2630         }
2631
2632         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2633         if (!option) {
2634                 return NULL;
2635         }
2636
2637         *option = *r;
2638
2639         if (!option->count) {
2640                 return option;
2641         }
2642
2643         option->types = talloc_zero_array(option,
2644                 struct spoolss_NotifyOptionType, option->count);
2645         if (!option->types) {
2646                 talloc_free(option);
2647                 return NULL;
2648         }
2649
2650         for (i=0; i < option->count; i++) {
2651                 option->types[i] = r->types[i];
2652
2653                 if (option->types[i].count) {
2654                         option->types[i].fields = talloc_zero_array(option,
2655                                 union spoolss_Field, option->types[i].count);
2656                         if (!option->types[i].fields) {
2657                                 talloc_free(option);
2658                                 return NULL;
2659                         }
2660                         for (k=0; k<option->types[i].count; k++) {
2661                                 option->types[i].fields[k] =
2662                                         r->types[i].fields[k];
2663                         }
2664                 }
2665         }
2666
2667         return option;
2668 }
2669
2670 /****************************************************************
2671  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2672  *
2673  * before replying OK: status=0 a rpc call is made to the workstation
2674  * asking ReplyOpenPrinter
2675  *
2676  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2677  * called from api_spoolss_rffpcnex
2678 ****************************************************************/
2679
2680 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2681                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2682 {
2683         struct dcesrv_call_state *dce_call = p->dce_call;
2684         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
2685         const struct tsocket_address *remote_address =
2686                 dcesrv_connection_get_remote_address(dcesrv_conn);
2687         int snum = -1;
2688         struct spoolss_NotifyOption *option = r->in.notify_options;
2689         struct sockaddr_storage client_ss;
2690         ssize_t client_len;
2691
2692         /* store the notify value in the printer struct */
2693
2694         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2695
2696         if (!Printer) {
2697                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2698                         "Invalid handle (%s:%u:%u).\n",
2699                         OUR_HANDLE(r->in.handle)));
2700                 return WERR_INVALID_HANDLE;
2701         }
2702
2703         Printer->notify.flags           = r->in.flags;
2704         Printer->notify.options         = r->in.options;
2705         Printer->notify.printerlocal    = r->in.printer_local;
2706         Printer->notify.msg_ctx         = p->msg_ctx;
2707
2708         TALLOC_FREE(Printer->notify.option);
2709         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2710
2711         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2712
2713         /* Connect to the client machine and send a ReplyOpenPrinter */
2714
2715         if ( Printer->printer_type == SPLHND_SERVER)
2716                 snum = -1;
2717         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2718                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2719                 return WERR_INVALID_HANDLE;
2720
2721         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2722                   "remote_address is %s\n",
2723                   tsocket_address_string(remote_address, p->mem_ctx)));
2724
2725         if (!lp_print_notify_backchannel(snum)) {
2726                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2727                         "backchannel disabled\n"));
2728                 return WERR_RPC_S_SERVER_UNAVAILABLE;
2729         }
2730
2731         client_len = tsocket_address_bsd_sockaddr(remote_address,
2732                                                   (struct sockaddr *) &client_ss,
2733                                                   sizeof(struct sockaddr_storage));
2734         if (client_len < 0) {
2735                 return WERR_NOT_ENOUGH_MEMORY;
2736         }
2737
2738         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2739                                         Printer->notify.printerlocal, REG_SZ,
2740                                         &Printer->notify.cli_hnd,
2741                                         &Printer->notify.cli_chan,
2742                                         &client_ss, p->msg_ctx)) {
2743                 return WERR_RPC_S_SERVER_UNAVAILABLE;
2744         }
2745
2746         return WERR_OK;
2747 }
2748
2749 /*******************************************************************
2750  * fill a notify_info_data with the servername
2751  ********************************************************************/
2752
2753 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2754                                        int snum,
2755                                        struct spoolss_Notify *data,
2756                                        print_queue_struct *queue,
2757                                        struct spoolss_PrinterInfo2 *pinfo2,
2758                                        TALLOC_CTX *mem_ctx)
2759 {
2760         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2761 }
2762
2763 /*******************************************************************
2764  * fill a notify_info_data with the printername (not including the servername).
2765  ********************************************************************/
2766
2767 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2768                                         int snum,
2769                                         struct spoolss_Notify *data,
2770                                         print_queue_struct *queue,
2771                                         struct spoolss_PrinterInfo2 *pinfo2,
2772                                         TALLOC_CTX *mem_ctx)
2773 {
2774         /* the notify name should not contain the \\server\ part */
2775         const char *p = strrchr(pinfo2->printername, '\\');
2776
2777         if (!p) {
2778                 p = pinfo2->printername;
2779         } else {
2780                 p++;
2781         }
2782
2783         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2784 }
2785
2786 /*******************************************************************
2787  * fill a notify_info_data with the servicename
2788  ********************************************************************/
2789
2790 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2791                                       int snum,
2792                                       struct spoolss_Notify *data,
2793                                       print_queue_struct *queue,
2794                                       struct spoolss_PrinterInfo2 *pinfo2,
2795                                       TALLOC_CTX *mem_ctx)
2796 {
2797         const struct loadparm_substitution *lp_sub =
2798                 loadparm_s3_global_substitution();
2799
2800         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), lp_sub, snum));
2801 }
2802
2803 /*******************************************************************
2804  * fill a notify_info_data with the port name
2805  ********************************************************************/
2806
2807 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2808                                      int snum,
2809                                      struct spoolss_Notify *data,
2810                                      print_queue_struct *queue,
2811                                      struct spoolss_PrinterInfo2 *pinfo2,
2812                                      TALLOC_CTX *mem_ctx)
2813 {
2814         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2815 }
2816
2817 /*******************************************************************
2818  * fill a notify_info_data with the printername
2819  * but it doesn't exist, have to see what to do
2820  ********************************************************************/
2821
2822 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2823                                        int snum,
2824                                        struct spoolss_Notify *data,
2825                                        print_queue_struct *queue,
2826                                        struct spoolss_PrinterInfo2 *pinfo2,
2827                                        TALLOC_CTX *mem_ctx)
2828 {
2829         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2830 }
2831
2832 /*******************************************************************
2833  * fill a notify_info_data with the comment
2834  ********************************************************************/
2835
2836 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2837                                    int snum,
2838                                    struct spoolss_Notify *data,
2839                                    print_queue_struct *queue,
2840                                    struct spoolss_PrinterInfo2 *pinfo2,
2841                                    TALLOC_CTX *mem_ctx)
2842 {
2843         const struct loadparm_substitution *lp_sub =
2844                 loadparm_s3_global_substitution();
2845         const char *p;
2846
2847         if (*pinfo2->comment == '\0') {
2848                 p = lp_comment(talloc_tos(), lp_sub, snum);
2849         } else {
2850                 p = pinfo2->comment;
2851         }
2852
2853         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2854 }
2855
2856 /*******************************************************************
2857  * fill a notify_info_data with the comment
2858  * location = "Room 1, floor 2, building 3"
2859  ********************************************************************/
2860
2861 static void spoolss_notify_location(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         const char *loc = pinfo2->location;
2869         NTSTATUS status;
2870
2871         status = printer_list_get_printer(mem_ctx,
2872                                           pinfo2->sharename,
2873                                           NULL,
2874                                           &loc,
2875                                           NULL);
2876         if (NT_STATUS_IS_OK(status)) {
2877                 if (loc == NULL) {
2878                         loc = pinfo2->location;
2879                 }
2880         }
2881
2882         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2883 }
2884
2885 /*******************************************************************
2886  * fill a notify_info_data with the device mode
2887  * jfm:xxxx don't to it for know but that's a real problem !!!
2888  ********************************************************************/
2889
2890 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2891                                    int snum,
2892                                    struct spoolss_Notify *data,
2893                                    print_queue_struct *queue,
2894                                    struct spoolss_PrinterInfo2 *pinfo2,
2895                                    TALLOC_CTX *mem_ctx)
2896 {
2897         /* for a dummy implementation we have to zero the fields */
2898         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2899 }
2900
2901 /*******************************************************************
2902  * fill a notify_info_data with the separator file name
2903  ********************************************************************/
2904
2905 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2906                                    int snum,
2907                                    struct spoolss_Notify *data,
2908                                    print_queue_struct *queue,
2909                                    struct spoolss_PrinterInfo2 *pinfo2,
2910                                    TALLOC_CTX *mem_ctx)
2911 {
2912         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2913 }
2914
2915 /*******************************************************************
2916  * fill a notify_info_data with the print processor
2917  * jfm:xxxx return always winprint to indicate we don't do anything to it
2918  ********************************************************************/
2919
2920 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2921                                            int snum,
2922                                            struct spoolss_Notify *data,
2923                                            print_queue_struct *queue,
2924                                            struct spoolss_PrinterInfo2 *pinfo2,
2925                                            TALLOC_CTX *mem_ctx)
2926 {
2927         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2928 }
2929
2930 /*******************************************************************
2931  * fill a notify_info_data with the print processor options
2932  * jfm:xxxx send an empty string
2933  ********************************************************************/
2934
2935 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2936                                       int snum,
2937                                       struct spoolss_Notify *data,
2938                                       print_queue_struct *queue,
2939                                       struct spoolss_PrinterInfo2 *pinfo2,
2940                                       TALLOC_CTX *mem_ctx)
2941 {
2942         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2943 }
2944
2945 /*******************************************************************
2946  * fill a notify_info_data with the data type
2947  * jfm:xxxx always send RAW as data type
2948  ********************************************************************/
2949
2950 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2951                                     int snum,
2952                                     struct spoolss_Notify *data,
2953                                     print_queue_struct *queue,
2954                                     struct spoolss_PrinterInfo2 *pinfo2,
2955                                     TALLOC_CTX *mem_ctx)
2956 {
2957         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2958 }
2959
2960 /*******************************************************************
2961  * fill a notify_info_data with the security descriptor
2962  * jfm:xxxx send an null pointer to say no security desc
2963  * have to implement security before !
2964  ********************************************************************/
2965
2966 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2967                                          int snum,
2968                                          struct spoolss_Notify *data,
2969                                          print_queue_struct *queue,
2970                                          struct spoolss_PrinterInfo2 *pinfo2,
2971                                          TALLOC_CTX *mem_ctx)
2972 {
2973         if (pinfo2->secdesc == NULL) {
2974                 data->data.sd.sd = NULL;
2975         } else {
2976                 data->data.sd.sd = security_descriptor_copy(mem_ctx,
2977                                                             pinfo2->secdesc);
2978         }
2979         data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2980                                                              0);
2981 }
2982
2983 /*******************************************************************
2984  * fill a notify_info_data with the attributes
2985  * jfm:xxxx a samba printer is always shared
2986  ********************************************************************/
2987
2988 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2989                                       int snum,
2990                                       struct spoolss_Notify *data,
2991                                       print_queue_struct *queue,
2992                                       struct spoolss_PrinterInfo2 *pinfo2,
2993                                       TALLOC_CTX *mem_ctx)
2994 {
2995         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2996 }
2997
2998 /*******************************************************************
2999  * fill a notify_info_data with the priority
3000  ********************************************************************/
3001
3002 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3003                                     int snum,
3004                                     struct spoolss_Notify *data,
3005                                     print_queue_struct *queue,
3006                                     struct spoolss_PrinterInfo2 *pinfo2,
3007                                     TALLOC_CTX *mem_ctx)
3008 {
3009         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3010 }
3011
3012 /*******************************************************************
3013  * fill a notify_info_data with the default priority
3014  ********************************************************************/
3015
3016 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3017                                             int snum,
3018                                             struct spoolss_Notify *data,
3019                                             print_queue_struct *queue,
3020                                             struct spoolss_PrinterInfo2 *pinfo2,
3021                                             TALLOC_CTX *mem_ctx)
3022 {
3023         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3024 }
3025
3026 /*******************************************************************
3027  * fill a notify_info_data with the start time
3028  ********************************************************************/
3029
3030 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3031                                       int snum,
3032                                       struct spoolss_Notify *data,
3033                                       print_queue_struct *queue,
3034                                       struct spoolss_PrinterInfo2 *pinfo2,
3035                                       TALLOC_CTX *mem_ctx)
3036 {
3037         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3038 }
3039
3040 /*******************************************************************
3041  * fill a notify_info_data with the until time
3042  ********************************************************************/
3043
3044 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3045                                       int snum,
3046                                       struct spoolss_Notify *data,
3047                                       print_queue_struct *queue,
3048                                       struct spoolss_PrinterInfo2 *pinfo2,
3049                                       TALLOC_CTX *mem_ctx)
3050 {
3051         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3052 }
3053
3054 /*******************************************************************
3055  * fill a notify_info_data with the status
3056  ********************************************************************/
3057
3058 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3059                                   int snum,
3060                                   struct spoolss_Notify *data,
3061                                   print_queue_struct *queue,
3062                                   struct spoolss_PrinterInfo2 *pinfo2,
3063                                   TALLOC_CTX *mem_ctx)
3064 {
3065         print_status_struct status;
3066
3067         print_queue_length(msg_ctx, snum, &status);
3068         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3069 }
3070
3071 /*******************************************************************
3072  * fill a notify_info_data with the number of jobs queued
3073  ********************************************************************/
3074
3075 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3076                                  int snum,
3077                                  struct spoolss_Notify *data,
3078                                  print_queue_struct *queue,
3079                                  struct spoolss_PrinterInfo2 *pinfo2,
3080                                  TALLOC_CTX *mem_ctx)
3081 {
3082         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3083                 data, print_queue_length(msg_ctx, snum, NULL));
3084 }
3085
3086 /*******************************************************************
3087  * fill a notify_info_data with the average ppm
3088  ********************************************************************/
3089
3090 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3091                                        int snum,
3092                                        struct spoolss_Notify *data,
3093                                        print_queue_struct *queue,
3094                                        struct spoolss_PrinterInfo2 *pinfo2,
3095                                        TALLOC_CTX *mem_ctx)
3096 {
3097         /* always respond 8 pages per minutes */
3098         /* a little hard ! */
3099         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3100 }
3101
3102 /*******************************************************************
3103  * fill a notify_info_data with username
3104  ********************************************************************/
3105
3106 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3107                                     int snum,
3108                                     struct spoolss_Notify *data,
3109                                     print_queue_struct *queue,
3110                                     struct spoolss_PrinterInfo2 *pinfo2,
3111                                     TALLOC_CTX *mem_ctx)
3112 {
3113         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3114 }
3115
3116 /*******************************************************************
3117  * fill a notify_info_data with job status
3118  ********************************************************************/
3119
3120 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3121                                       int snum,
3122                                       struct spoolss_Notify *data,
3123                                       print_queue_struct *queue,
3124                                       struct spoolss_PrinterInfo2 *pinfo2,
3125                                       TALLOC_CTX *mem_ctx)
3126 {
3127         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3128 }
3129
3130 /*******************************************************************
3131  * fill a notify_info_data with job name
3132  ********************************************************************/
3133
3134 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3135                                     int snum,
3136                                     struct spoolss_Notify *data,
3137                                     print_queue_struct *queue,
3138                                     struct spoolss_PrinterInfo2 *pinfo2,
3139                                     TALLOC_CTX *mem_ctx)
3140 {
3141         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3142 }
3143
3144 /*******************************************************************
3145  * fill a notify_info_data with job status
3146  ********************************************************************/
3147
3148 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3149                                              int snum,
3150                                              struct spoolss_Notify *data,
3151                                              print_queue_struct *queue,
3152                                              struct spoolss_PrinterInfo2 *pinfo2,
3153                                              TALLOC_CTX *mem_ctx)
3154 {
3155         /*
3156          * Now we're returning job status codes we just return a "" here. JRA.
3157          */
3158
3159         const char *p = "";
3160
3161 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3162         p = "unknown";
3163
3164         switch (queue->status) {
3165         case LPQ_QUEUED:
3166                 p = "Queued";
3167                 break;
3168         case LPQ_PAUSED:
3169                 p = "";    /* NT provides the paused string */
3170                 break;
3171         case LPQ_SPOOLING:
3172                 p = "Spooling";
3173                 break;
3174         case LPQ_PRINTING:
3175                 p = "Printing";
3176                 break;
3177         }
3178 #endif /* NO LONGER NEEDED. */
3179
3180         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3181 }
3182
3183 /*******************************************************************
3184  * fill a notify_info_data with job time
3185  ********************************************************************/
3186
3187 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3188                                     int snum,
3189                                     struct spoolss_Notify *data,
3190                                     print_queue_struct *queue,
3191                                     struct spoolss_PrinterInfo2 *pinfo2,
3192                                     TALLOC_CTX *mem_ctx)
3193 {
3194         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3195 }
3196
3197 /*******************************************************************
3198  * fill a notify_info_data with job size
3199  ********************************************************************/
3200
3201 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3202                                     int snum,
3203                                     struct spoolss_Notify *data,
3204                                     print_queue_struct *queue,
3205                                     struct spoolss_PrinterInfo2 *pinfo2,
3206                                     TALLOC_CTX *mem_ctx)
3207 {
3208         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3209 }
3210
3211 /*******************************************************************
3212  * fill a notify_info_data with page info
3213  ********************************************************************/
3214 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3215                                        int snum,
3216                                 struct spoolss_Notify *data,
3217                                 print_queue_struct *queue,
3218                                 struct spoolss_PrinterInfo2 *pinfo2,
3219                                 TALLOC_CTX *mem_ctx)
3220 {
3221         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3222 }
3223
3224 /*******************************************************************
3225  * fill a notify_info_data with pages printed info.
3226  ********************************************************************/
3227 static void spoolss_notify_pages_printed(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         /* Add code when back-end tracks this */
3235         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3236 }
3237
3238 /*******************************************************************
3239  Fill a notify_info_data with job position.
3240  ********************************************************************/
3241
3242 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3243                                         int snum,
3244                                         struct spoolss_Notify *data,
3245                                         print_queue_struct *queue,
3246                                         struct spoolss_PrinterInfo2 *pinfo2,
3247                                         TALLOC_CTX *mem_ctx)
3248 {
3249         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3250 }
3251
3252 /*******************************************************************
3253  Fill a notify_info_data with submitted time.
3254  ********************************************************************/
3255
3256 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3257                                           int snum,
3258                                           struct spoolss_Notify *data,
3259                                           print_queue_struct *queue,
3260                                           struct spoolss_PrinterInfo2 *pinfo2,
3261                                           TALLOC_CTX *mem_ctx)
3262 {
3263         data->data.string.string = NULL;
3264         data->data.string.size = 0;
3265
3266         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3267                                &data->data.string.string,
3268                                &data->data.string.size);
3269
3270 }
3271
3272 struct s_notify_info_data_table
3273 {
3274         enum spoolss_NotifyType type;
3275         uint16_t field;
3276         const char *name;
3277         enum spoolss_NotifyTable variable_type;
3278         void (*fn) (struct messaging_context *msg_ctx,
3279                     int snum, struct spoolss_Notify *data,
3280                     print_queue_struct *queue,
3281                     struct spoolss_PrinterInfo2 *pinfo2,
3282                     TALLOC_CTX *mem_ctx);
3283 };
3284
3285 /* A table describing the various print notification constants and
3286    whether the notification data is a pointer to a variable sized
3287    buffer, a one value uint32_t or a two value uint32_t. */
3288
3289 static const struct s_notify_info_data_table notify_info_data_table[] =
3290 {
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3317 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3318 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3319 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3320 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3321 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3322 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3323 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3324 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3325 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3326 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3327 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3328 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3329 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3330 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3331 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3332 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3333 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3334 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3335 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3336 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3337 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3338 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3339 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3340 };
3341
3342 /*******************************************************************
3343  Return the variable_type of info_data structure.
3344 ********************************************************************/
3345
3346 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3347                                                                   uint16_t field)
3348 {
3349         int i=0;
3350
3351         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3352                 if ( (notify_info_data_table[i].type == type) &&
3353                      (notify_info_data_table[i].field == field) ) {
3354                         return notify_info_data_table[i].variable_type;
3355                 }
3356         }
3357
3358         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3359
3360         return (enum spoolss_NotifyTable) 0;
3361 }
3362
3363 /****************************************************************************
3364 ****************************************************************************/
3365
3366 static bool search_notify(enum spoolss_NotifyType type,
3367                           uint16_t field,
3368                           int *value)
3369 {
3370         int i;
3371
3372         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3373                 if (notify_info_data_table[i].type == type &&
3374                     notify_info_data_table[i].field == field &&
3375                     notify_info_data_table[i].fn != NULL) {
3376                         *value = i;
3377                         return true;
3378                 }
3379         }
3380
3381         return false;
3382 }
3383
3384 /****************************************************************************
3385 ****************************************************************************/
3386
3387 static void construct_info_data(struct spoolss_Notify *info_data,
3388                                 enum spoolss_NotifyType type,
3389                                 uint16_t field, int id)
3390 {
3391         info_data->type                 = type;
3392         info_data->field.field          = field;
3393         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3394         info_data->job_id               = id;
3395 }
3396
3397 /*******************************************************************
3398  *
3399  * fill a notify_info struct with info asked
3400  *
3401  ********************************************************************/
3402
3403 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3404                                           struct printer_handle *print_hnd,
3405                                           struct spoolss_NotifyInfo *info,
3406                                           struct spoolss_PrinterInfo2 *pinfo2,
3407                                           int snum,
3408                                           const struct spoolss_NotifyOptionType *option_type,
3409                                           uint32_t id,
3410                                           TALLOC_CTX *mem_ctx)
3411 {
3412         const struct loadparm_substitution *lp_sub =
3413                 loadparm_s3_global_substitution();
3414         int field_num,j;
3415         enum spoolss_NotifyType type;
3416         uint16_t field;
3417
3418         struct spoolss_Notify *current_data;
3419
3420         type = option_type->type;
3421
3422         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3423                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3424                 option_type->count, lp_servicename(talloc_tos(), lp_sub, snum)));
3425
3426         for(field_num=0; field_num < option_type->count; field_num++) {
3427                 field = option_type->fields[field_num].field;
3428
3429                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3430
3431                 if (!search_notify(type, field, &j) )
3432                         continue;
3433
3434                 info->notifies = talloc_realloc(info, info->notifies,
3435                                                       struct spoolss_Notify,
3436                                                       info->count + 1);
3437                 if (info->notifies == NULL) {
3438                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3439                         return false;
3440                 }
3441
3442                 current_data = &info->notifies[info->count];
3443
3444                 construct_info_data(current_data, type, field, id);
3445
3446                 DEBUG(10, ("construct_notify_printer_info: "
3447                            "calling [%s]  snum=%d  printername=[%s])\n",
3448                            notify_info_data_table[j].name, snum,
3449                            pinfo2->printername));
3450
3451                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3452                                              NULL, pinfo2, mem_ctx);
3453
3454                 info->count++;
3455         }
3456
3457         return true;
3458 }
3459
3460 /*******************************************************************
3461  *
3462  * fill a notify_info struct with info asked
3463  *
3464  ********************************************************************/
3465
3466 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3467                                        print_queue_struct *queue,
3468                                        struct spoolss_NotifyInfo *info,
3469                                        struct spoolss_PrinterInfo2 *pinfo2,
3470                                        int snum,
3471                                        const struct spoolss_NotifyOptionType *option_type,
3472                                        uint32_t id,
3473                                        TALLOC_CTX *mem_ctx)
3474 {
3475         int field_num,j;
3476         enum spoolss_NotifyType type;
3477         uint16_t field;
3478         struct spoolss_Notify *current_data;
3479
3480         DEBUG(4,("construct_notify_jobs_info\n"));
3481
3482         type = option_type->type;
3483
3484         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3485                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3486                 option_type->count));
3487
3488         for(field_num=0; field_num<option_type->count; field_num++) {
3489                 field = option_type->fields[field_num].field;
3490
3491                 if (!search_notify(type, field, &j) )
3492                         continue;
3493
3494                 info->notifies = talloc_realloc(info, info->notifies,
3495                                                       struct spoolss_Notify,
3496                                                       info->count + 1);
3497                 if (info->notifies == NULL) {
3498                         DEBUG(2,("construct_notify_jobs_info: failed to enlarge buffer info->data!\n"));
3499                         return false;
3500                 }
3501
3502                 current_data=&(info->notifies[info->count]);
3503
3504                 construct_info_data(current_data, type, field, id);
3505                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3506                                              queue, pinfo2, mem_ctx);
3507                 info->count++;
3508         }
3509
3510         return true;
3511 }
3512
3513 /*
3514  * JFM: The enumeration is not that simple, it's even non obvious.
3515  *
3516  * let's take an example: I want to monitor the PRINTER SERVER for
3517  * the printer's name and the number of jobs currently queued.
3518  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3519  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3520  *
3521  * I have 3 printers on the back of my server.
3522  *
3523  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3524  * structures.
3525  *   Number     Data                    Id
3526  *      1       printer 1 name          1
3527  *      2       printer 1 cjob          1
3528  *      3       printer 2 name          2
3529  *      4       printer 2 cjob          2
3530  *      5       printer 3 name          3
3531  *      6       printer 3 name          3
3532  *
3533  * that's the print server case, the printer case is even worse.
3534  */
3535
3536 /*******************************************************************
3537  *
3538  * enumerate all printers on the printserver
3539  * fill a notify_info struct with info asked
3540  *
3541  ********************************************************************/
3542
3543 static WERROR printserver_notify_info(struct pipes_struct *p,
3544                                       struct policy_handle *hnd,
3545                                       struct spoolss_NotifyInfo *info,
3546                                       TALLOC_CTX *mem_ctx)
3547 {
3548         const struct loadparm_substitution *lp_sub =
3549                 loadparm_s3_global_substitution();
3550         int snum;
3551         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3552         int n_services=lp_numservices();
3553         int i;
3554         struct spoolss_NotifyOption *option;
3555         struct spoolss_NotifyOptionType option_type;
3556         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3557         WERROR result;
3558
3559         DEBUG(4,("printserver_notify_info\n"));
3560
3561         if (!Printer)
3562                 return WERR_INVALID_HANDLE;
3563
3564         option = Printer->notify.option;
3565
3566         info->version   = 2;
3567         info->notifies  = NULL;
3568         info->count     = 0;
3569
3570         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3571            sending a ffpcn() request first */
3572
3573         if ( !option )
3574                 return WERR_INVALID_HANDLE;
3575
3576         for (i=0; i<option->count; i++) {
3577                 option_type = option->types[i];
3578
3579                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3580                         continue;
3581
3582                 for (snum = 0; snum < n_services; snum++) {
3583                         if (!lp_browseable(snum) ||
3584                             !lp_snum_ok(snum) ||
3585                             !lp_printable(snum)) {
3586                                 continue; /* skip */
3587                         }
3588
3589                         /* Maybe we should use the SYSTEM session_info here... */
3590                         result = winreg_get_printer_internal(mem_ctx,
3591                                                     get_session_info_system(),
3592                                                     p->msg_ctx,
3593                                                     lp_servicename(talloc_tos(), lp_sub, snum),
3594                                                     &pinfo2);
3595                         if (!W_ERROR_IS_OK(result)) {
3596                                 DEBUG(4, ("printserver_notify_info: "
3597                                           "Failed to get printer [%s]\n",
3598                                           lp_servicename(talloc_tos(), lp_sub, snum)));
3599                                 continue;
3600                         }
3601
3602
3603                         construct_notify_printer_info(p->msg_ctx,
3604                                                       Printer, info,
3605                                                       pinfo2, snum,
3606                                                       &option_type, snum,
3607                                                       mem_ctx);
3608
3609                         TALLOC_FREE(pinfo2);
3610                 }
3611         }
3612
3613 #if 0
3614         /*
3615          * Debugging information, don't delete.
3616          */
3617
3618         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3619         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3620         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3621
3622         for (i=0; i<info->count; i++) {
3623                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3624                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3625                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3626         }
3627 #endif
3628
3629         return WERR_OK;
3630 }
3631
3632 /*******************************************************************
3633  *
3634  * fill a notify_info struct with info asked
3635  *
3636  ********************************************************************/
3637
3638 static WERROR printer_notify_info(struct pipes_struct *p,
3639                                   struct policy_handle *hnd,
3640                                   struct spoolss_NotifyInfo *info,
3641                                   TALLOC_CTX *mem_ctx)
3642 {
3643         const struct loadparm_substitution *lp_sub =
3644                 loadparm_s3_global_substitution();
3645         int snum;
3646         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3647         int i;
3648         uint32_t id;
3649         struct spoolss_NotifyOption *option;
3650         struct spoolss_NotifyOptionType option_type;
3651         int count,j;
3652         print_queue_struct *queue=NULL;
3653         print_status_struct status;
3654         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3655         WERROR result;
3656         struct tdb_print_db *pdb;
3657
3658         DEBUG(4,("printer_notify_info\n"));
3659
3660         if (!Printer)
3661                 return WERR_INVALID_HANDLE;
3662
3663         option = Printer->notify.option;
3664         id = 0x0;
3665
3666         info->version   = 2;
3667         info->notifies  = NULL;
3668         info->count     = 0;
3669
3670         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3671            sending a ffpcn() request first */
3672
3673         if ( !option )
3674                 return WERR_INVALID_HANDLE;
3675
3676         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3677                 return WERR_INVALID_HANDLE;
3678         }
3679
3680         pdb = get_print_db_byname(Printer->sharename);
3681         if (pdb == NULL) {
3682                 return WERR_INVALID_HANDLE;
3683         }
3684
3685         /* Maybe we should use the SYSTEM session_info here... */
3686         result = winreg_get_printer_internal(mem_ctx,
3687                                     get_session_info_system(),
3688                                     p->msg_ctx,
3689                                     lp_servicename(talloc_tos(), lp_sub, snum), &pinfo2);
3690         if (!W_ERROR_IS_OK(result)) {
3691                 result = WERR_INVALID_HANDLE;
3692                 goto err_pdb_drop;
3693         }
3694
3695         /*
3696          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3697          * correct servername.
3698          */
3699         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3700         if (pinfo2->servername == NULL) {
3701                 result = WERR_NOT_ENOUGH_MEMORY;
3702                 goto err_pdb_drop;
3703         }
3704
3705         for (i = 0; i < option->count; i++) {
3706                 option_type = option->types[i];
3707
3708                 switch (option_type.type) {
3709                 case PRINTER_NOTIFY_TYPE:
3710                         if (construct_notify_printer_info(p->msg_ctx,
3711                                                           Printer, info,
3712                                                           pinfo2, snum,
3713                                                           &option_type, id,
3714                                                           mem_ctx)) {
3715                                 id--;
3716                         }
3717                         break;
3718
3719                 case JOB_NOTIFY_TYPE:
3720
3721                         count = print_queue_status(p->msg_ctx, snum, &queue,
3722                                                    &status);
3723
3724                         for (j = 0; j < count; j++) {
3725                                 uint32_t jobid;
3726                                 jobid = sysjob_to_jobid_pdb(pdb,
3727                                                             queue[j].sysjob);
3728                                 if (jobid == (uint32_t)-1) {
3729                                         DEBUG(2, ("ignoring untracked job %d\n",
3730                                                   queue[j].sysjob));
3731                                         continue;
3732                                 }
3733                                 /* FIXME check return value */
3734                                 construct_notify_jobs_info(p->msg_ctx,
3735                                                            &queue[j], info,
3736                                                            pinfo2, snum,
3737                                                            &option_type,
3738                                                            jobid,
3739                                                            mem_ctx);
3740                         }
3741
3742                         SAFE_FREE(queue);
3743                         break;
3744                 }
3745         }
3746
3747         /*
3748          * Debugging information, don't delete.
3749          */
3750         /*
3751         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3752         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3753         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3754
3755         for (i=0; i<info->count; i++) {
3756                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3757                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3758                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3759         }
3760         */
3761
3762         talloc_free(pinfo2);
3763         result = WERR_OK;
3764 err_pdb_drop:
3765         release_print_db(pdb);
3766         return result;
3767 }
3768
3769 /****************************************************************
3770  _spoolss_RouterRefreshPrinterChangeNotify
3771 ****************************************************************/
3772
3773 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3774                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3775 {
3776         struct spoolss_NotifyInfo *info;
3777
3778         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3779         WERROR result = WERR_INVALID_HANDLE;
3780
3781         /* we always have a spoolss_NotifyInfo struct */
3782         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3783         if (!info) {
3784                 result = WERR_NOT_ENOUGH_MEMORY;
3785                 goto done;
3786         }
3787
3788         *r->out.info = info;
3789
3790         if (!Printer) {
3791                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3792                         "Invalid handle (%s:%u:%u).\n",
3793                         OUR_HANDLE(r->in.handle)));
3794                 goto done;
3795         }
3796
3797         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3798
3799         /*
3800          *      We are now using the change value, and
3801          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3802          *      I don't have a global notification system, I'm sending back all the
3803          *      information even when _NOTHING_ has changed.
3804          */
3805
3806         /* We need to keep track of the change value to send back in
3807            RRPCN replies otherwise our updates are ignored. */
3808
3809         Printer->notify.fnpcn = true;
3810
3811         if (Printer->notify.cli_chan != NULL &&
3812             Printer->notify.cli_chan->active_connections > 0) {
3813                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3814                         "Saving change value in request [%x]\n",
3815                         r->in.change_low));
3816                 Printer->notify.change = r->in.change_low;
3817         }
3818
3819         /* just ignore the spoolss_NotifyOption */
3820
3821         switch (Printer->printer_type) {
3822                 case SPLHND_SERVER:
3823                         result = printserver_notify_info(p, r->in.handle,
3824                                                          info, p->mem_ctx);
3825                         break;
3826
3827                 case SPLHND_PRINTER:
3828                         result = printer_notify_info(p, r->in.handle,
3829                                                      info, p->mem_ctx);
3830                         break;
3831         }
3832
3833         Printer->notify.fnpcn = false;
3834
3835 done:
3836         return result;
3837 }
3838
3839 /********************************************************************
3840  ********************************************************************/
3841
3842 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3843                                  const char *servername,
3844                                  const char *printername,
3845                                  const char **printername_p)
3846 {
3847         /* FIXME: add lp_force_printername() */
3848
3849         if (servername == NULL) {
3850                 *printername_p = talloc_strdup(mem_ctx, printername);
3851                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3852                 return WERR_OK;
3853         }
3854
3855         if (servername[0] == '\\' && servername[1] == '\\') {
3856                 servername += 2;
3857         }
3858
3859         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3860         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3861
3862         return WERR_OK;
3863 }
3864
3865 /********************************************************************
3866  ********************************************************************/
3867
3868 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3869                                           const char *printername)
3870 {
3871         if (dm == NULL) {
3872                 return;
3873         }
3874
3875         dm->devicename = talloc_strndup(dm, printername,
3876                                         MIN(strlen(printername), 31));
3877 }
3878
3879 /********************************************************************
3880  * construct_printer_info_0
3881  * fill a printer_info_0 struct
3882  ********************************************************************/
3883
3884 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3885                                       const struct auth_session_info *session_info,
3886                                       struct messaging_context *msg_ctx,
3887                                       struct spoolss_PrinterInfo2 *info2,
3888                                       const char *servername,
3889                                       struct spoolss_PrinterInfo0 *r,
3890                                       int snum)
3891 {
3892         int count;
3893         struct printer_session_counter *session_counter;
3894         struct timeval setuptime;
3895         print_status_struct status;
3896         WERROR result;
3897         int os_major, os_minor, os_build;
3898         const char *architecture;
3899         uint32_t processor_architecture, processor_type;
3900
3901         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3902         if (!W_ERROR_IS_OK(result)) {
3903                 return result;
3904         }
3905
3906         if (servername) {
3907                 r->servername = talloc_strdup(mem_ctx, servername);
3908                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3909         } else {
3910                 r->servername = NULL;
3911         }
3912
3913         count = print_queue_length(msg_ctx, snum, &status);
3914
3915         /* check if we already have a counter for this printer */
3916         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3917                 if (session_counter->snum == snum)
3918                         break;
3919         }
3920
3921         /* it's the first time, add it to the list */
3922         if (session_counter == NULL) {
3923                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3924                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3925                 session_counter->snum           = snum;
3926                 session_counter->counter        = 0;
3927                 DLIST_ADD(counter_list, session_counter);
3928         }
3929
3930         /* increment it */
3931         session_counter->counter++;
3932
3933         r->cjobs                        = count;
3934         r->total_jobs                   = 0;
3935         r->total_bytes                  = 0;
3936
3937         get_startup_time(&setuptime);
3938         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3939
3940         /* JFM:
3941          * the global_counter should be stored in a TDB as it's common to all the clients
3942          * and should be zeroed on samba startup
3943          */
3944         r->global_counter               = session_counter->counter;
3945         r->total_pages                  = 0;
3946
3947         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3948         os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
3949                                "spoolss", "os_major",
3950                                GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
3951         os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
3952                                "spoolss", "os_minor",
3953                                GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
3954         os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
3955                                "spoolss", "os_build",
3956                                GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
3957
3958         SCVAL(&r->version, 0, os_major);
3959         SCVAL(&r->version, 1, os_minor);
3960         SSVAL(&r->version, 2, os_build);
3961
3962         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
3963                                             "spoolss",
3964                                             "architecture",
3965                                             GLOBAL_SPOOLSS_ARCHITECTURE);
3966
3967         if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
3968                 processor_architecture  = PROCESSOR_ARCHITECTURE_AMD64;
3969                 processor_type          = PROCESSOR_AMD_X8664;
3970         } else if (strequal(architecture, SPOOLSS_ARCHITECTURE_ARM64)) {
3971                 processor_architecture  = PROCESSOR_ARCHITECTURE_ARM64;
3972                 processor_type          = PROCESSOR_ARM820;
3973         } else {
3974                 processor_architecture  = PROCESSOR_ARCHITECTURE_INTEL;
3975                 processor_type          = PROCESSOR_INTEL_PENTIUM;
3976         }
3977
3978         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3979         r->spooling                     = 0;
3980         r->max_spooling                 = 0;
3981         r->session_counter              = session_counter->counter;
3982         r->num_error_out_of_paper       = 0x0;
3983         r->num_error_not_ready          = 0x0;          /* number of print failure */
3984         r->job_error                    = 0x0;
3985         r->number_of_processors         = 0x1;
3986         r->processor_type               = processor_type;
3987         r->high_part_total_bytes        = 0x0;
3988
3989         /* ChangeID in milliseconds*/
3990         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3991                                     info2->sharename, &r->change_id);
3992
3993         r->last_error                   = WERR_OK;
3994         r->status                       = nt_printq_status(status.status);
3995         r->enumerate_network_printers   = 0x0;
3996         r->c_setprinter                 = 0x0;
3997         r->processor_architecture       = processor_architecture;
3998         r->processor_level              = 0x6;          /* 6  ???*/
3999         r->ref_ic                       = 0;
4000         r->reserved2                    = 0;
4001         r->reserved3                    = 0;
4002
4003         return WERR_OK;
4004 }
4005
4006
4007 /********************************************************************
4008  * construct_printer_info1
4009  * fill a spoolss_PrinterInfo1 struct
4010 ********************************************************************/
4011
4012 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4013                                       const struct spoolss_PrinterInfo2 *info2,
4014                                       uint32_t flags,
4015                                       const char *servername,
4016                                       struct spoolss_PrinterInfo1 *r,
4017                                       int snum)
4018 {
4019         const struct loadparm_substitution *lp_sub =
4020                 loadparm_s3_global_substitution();
4021         WERROR result;
4022
4023         r->flags                = flags;
4024
4025         if (info2->comment == NULL || info2->comment[0] == '\0') {
4026                 r->comment      = lp_comment(mem_ctx, lp_sub, snum);
4027         } else {
4028                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4029         }
4030         W_ERROR_HAVE_NO_MEMORY(r->comment);
4031
4032         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4033         if (!W_ERROR_IS_OK(result)) {
4034                 return result;
4035         }
4036
4037         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
4038                                                   r->name,
4039                                                   info2->drivername,
4040                                                   r->comment);
4041         W_ERROR_HAVE_NO_MEMORY(r->description);
4042
4043         return WERR_OK;
4044 }
4045
4046 /********************************************************************
4047  * construct_printer_info2
4048  * fill a spoolss_PrinterInfo2 struct
4049 ********************************************************************/
4050
4051 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4052                                       struct messaging_context *msg_ctx,
4053                                       const struct spoolss_PrinterInfo2 *info2,
4054                                       const char *servername,
4055                                       struct spoolss_PrinterInfo2 *r,
4056                                       int snum)
4057 {
4058         const struct loadparm_substitution *lp_sub =
4059                 loadparm_s3_global_substitution();
4060         int count;
4061         print_status_struct status;
4062         WERROR result;
4063
4064         count = print_queue_length(msg_ctx, snum, &status);
4065
4066         if (servername) {
4067                 r->servername           = talloc_strdup(mem_ctx, servername);
4068                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4069         } else {
4070                 r->servername           = NULL;
4071         }
4072
4073         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4074         if (!W_ERROR_IS_OK(result)) {
4075                 return result;
4076         }
4077
4078         r->sharename            = lp_servicename(mem_ctx, lp_sub, snum);
4079         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4080         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4081         W_ERROR_HAVE_NO_MEMORY(r->portname);
4082         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4083         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4084
4085         if (info2->comment[0] == '\0') {
4086                 r->comment      = lp_comment(mem_ctx, lp_sub, snum);
4087         } else {
4088                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4089         }
4090         W_ERROR_HAVE_NO_MEMORY(r->comment);
4091
4092         r->location     = talloc_strdup(mem_ctx, info2->location);
4093         if (info2->location[0] == '\0') {
4094                 const char *loc = NULL;
4095                 NTSTATUS nt_status;
4096
4097                 nt_status = printer_list_get_printer(mem_ctx,
4098                                                      info2->sharename,
4099                                                      NULL,
4100                                                      &loc,
4101                                                      NULL);
4102                 if (NT_STATUS_IS_OK(nt_status)) {
4103                         if (loc != NULL) {
4104                                 r->location = talloc_strdup(mem_ctx, loc);
4105                         }
4106                 }
4107         }
4108         W_ERROR_HAVE_NO_MEMORY(r->location);
4109
4110         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4111         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4112         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4113         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4114         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4115         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4116         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4117         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4118
4119         r->attributes           = info2->attributes;
4120
4121         r->priority             = info2->priority;
4122         r->defaultpriority      = info2->defaultpriority;
4123         r->starttime            = info2->starttime;
4124         r->untiltime            = info2->untiltime;
4125         r->status               = nt_printq_status(status.status);
4126         r->cjobs                = count;
4127         r->averageppm           = info2->averageppm;
4128
4129         if (info2->devmode != NULL) {
4130                 result = copy_devicemode(mem_ctx,
4131                                          info2->devmode,
4132                                          &r->devmode);
4133                 if (!W_ERROR_IS_OK(result)) {
4134                         return result;
4135                 }
4136         } else if (lp_default_devmode(snum)) {
4137                 result = spoolss_create_default_devmode(mem_ctx,
4138                                                         info2->printername,
4139                                                         &r->devmode);
4140                 if (!W_ERROR_IS_OK(result)) {
4141                         return result;
4142                 }
4143         } else {
4144                 r->devmode = NULL;
4145                 DEBUG(8,("Returning NULL Devicemode!\n"));
4146         }
4147
4148         compose_devicemode_devicename(r->devmode, r->printername);
4149
4150         r->secdesc = NULL;
4151
4152         if (info2->secdesc != NULL) {
4153                 /* don't use talloc_steal() here unless you do a deep steal of all
4154                    the SEC_DESC members */
4155
4156                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4157                 if (r->secdesc == NULL) {
4158                         return WERR_NOT_ENOUGH_MEMORY;
4159                 }
4160         }
4161
4162         return WERR_OK;
4163 }
4164
4165 /********************************************************************
4166  * construct_printer_info3
4167  * fill a spoolss_PrinterInfo3 struct
4168  ********************************************************************/
4169
4170 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4171                                       const struct spoolss_PrinterInfo2 *info2,
4172                                       const char *servername,
4173                                       struct spoolss_PrinterInfo3 *r,
4174                                       int snum)
4175 {
4176         /* These are the components of the SD we are returning. */
4177
4178         if (info2->secdesc != NULL) {
4179                 /* don't use talloc_steal() here unless you do a deep steal of all
4180                    the SEC_DESC members */
4181
4182                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4183                 if (r->secdesc == NULL) {
4184                         return WERR_NOT_ENOUGH_MEMORY;
4185                 }
4186         }
4187
4188         return WERR_OK;
4189 }
4190
4191 /********************************************************************
4192  * construct_printer_info4
4193  * fill a spoolss_PrinterInfo4 struct
4194  ********************************************************************/
4195
4196 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4197                                       const struct spoolss_PrinterInfo2 *info2,
4198                                       const char *servername,
4199                                       struct spoolss_PrinterInfo4 *r,
4200                                       int snum)
4201 {
4202         WERROR result;
4203
4204         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4205         if (!W_ERROR_IS_OK(result)) {
4206                 return result;
4207         }
4208
4209         if (servername) {
4210                 r->servername   = talloc_strdup(mem_ctx, servername);
4211                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4212         } else {
4213                 r->servername = NULL;
4214         }
4215
4216         r->attributes   = info2->attributes;
4217
4218         return WERR_OK;
4219 }
4220
4221 /********************************************************************
4222  * construct_printer_info5
4223  * fill a spoolss_PrinterInfo5 struct
4224  ********************************************************************/
4225
4226 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4227                                       const struct spoolss_PrinterInfo2 *info2,
4228                                       const char *servername,
4229                                       struct spoolss_PrinterInfo5 *r,
4230                                       int snum)
4231 {
4232         WERROR result;
4233
4234         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4235         if (!W_ERROR_IS_OK(result)) {
4236                 return result;
4237         }
4238
4239         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4240         W_ERROR_HAVE_NO_MEMORY(r->portname);
4241
4242         r->attributes   = info2->attributes;
4243
4244         /*
4245          * These two are not used by NT+ according to MSDN. However the values
4246          * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
4247          */
4248         r->device_not_selected_timeout          = 0xafc8; /* 45 sec */
4249         r->transmission_retry_timeout           = 0xafc8; /* 45 sec */
4250
4251         return WERR_OK;
4252 }
4253
4254 /********************************************************************
4255  * construct_printer_info_6
4256  * fill a spoolss_PrinterInfo6 struct
4257  ********************************************************************/
4258
4259 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4260                                       struct messaging_context *msg_ctx,
4261                                       const struct spoolss_PrinterInfo2 *info2,
4262                                       const char *servername,
4263                                       struct spoolss_PrinterInfo6 *r,
4264                                       int snum)
4265 {
4266         print_status_struct status;
4267
4268         print_queue_length(msg_ctx, snum, &status);
4269
4270         r->status = nt_printq_status(status.status);
4271
4272         return WERR_OK;
4273 }
4274
4275 /********************************************************************
4276  * construct_printer_info7
4277  * fill a spoolss_PrinterInfo7 struct
4278  ********************************************************************/
4279
4280 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4281                                       struct messaging_context *msg_ctx,
4282                                       const char *servername,
4283                                       struct spoolss_PrinterInfo7 *r,
4284                                       int snum)
4285 {
4286         const struct loadparm_substitution *lp_sub =
4287                 loadparm_s3_global_substitution();
4288         const struct auth_session_info *session_info;
4289         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4290         char *printer;
4291         WERROR werr;
4292         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4293         if (tmp_ctx == NULL) {
4294                 return WERR_NOT_ENOUGH_MEMORY;
4295         }
4296
4297         session_info = get_session_info_system();
4298         SMB_ASSERT(session_info != NULL);
4299
4300         printer = lp_servicename(tmp_ctx, lp_sub, snum);
4301         if (printer == NULL) {
4302                 DEBUG(0, ("invalid printer snum %d\n", snum));
4303                 werr = WERR_INVALID_PARAMETER;
4304                 goto out_tmp_free;
4305         }
4306
4307         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4308                                  servername, printer, &pinfo2)) {
4309                 struct GUID guid;
4310                 char *guidstr;
4311                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4312                                            printer, &guid);
4313                 if (!W_ERROR_IS_OK(werr)) {
4314                         /*
4315                          * If we do not have a GUID entry in the registry, then
4316                          * try to retrieve it from AD and store it now.
4317                          */
4318                         werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4319                                                         &guid);
4320                         if (!W_ERROR_IS_OK(werr)) {
4321                                 DBG_NOTICE("Failed to retrieve GUID for "
4322                                            "printer [%s] from AD - %s\n",
4323                                            printer,
4324                                            win_errstr(werr));
4325                                 if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
4326                                         /*
4327                                          * If we did not find it in AD, then it
4328                                          * is unpublished and we should reflect
4329                                          * this in the registry and return
4330                                          * success.
4331                                          */
4332                                         DBG_WARNING("Unpublish printer [%s]\n",
4333                                                     pinfo2->sharename);
4334                                         nt_printer_publish(tmp_ctx,
4335                                                            session_info,
4336                                                            msg_ctx,
4337                                                            pinfo2,
4338                                                            DSPRINT_UNPUBLISH);
4339                                         r->guid = talloc_strdup(mem_ctx, "");
4340                                         r->action = DSPRINT_UNPUBLISH;
4341
4342                                         if (r->guid == NULL) {
4343                                                 werr = WERR_NOT_ENOUGH_MEMORY;
4344                                         } else {
4345                                                 werr = WERR_OK;
4346                                         }
4347                                 }
4348                                 goto out_tmp_free;
4349                         }
4350
4351                         werr = nt_printer_guid_store(msg_ctx, printer, guid);
4352                         if (!W_ERROR_IS_OK(werr)) {
4353                                 DEBUG(3, ("failed to store printer %s guid\n",
4354                                           printer));
4355                         }
4356                 }
4357
4358                 /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
4359                 guidstr = GUID_string2(mem_ctx, &guid);
4360                 if (guidstr == NULL) {
4361                         werr = WERR_NOT_ENOUGH_MEMORY;
4362                         goto out_tmp_free;
4363                 }
4364                 /* Convert GUID string to uppercase otherwise printers
4365                  * are pruned */
4366                 r->guid = talloc_strdup_upper(mem_ctx, guidstr);
4367                 r->action = DSPRINT_PUBLISH;
4368
4369                 TALLOC_FREE(guidstr);
4370         } else {
4371                 r->guid = talloc_strdup(mem_ctx, "");
4372                 r->action = DSPRINT_UNPUBLISH;
4373         }
4374         if (r->guid == NULL) {
4375                 werr = WERR_NOT_ENOUGH_MEMORY;
4376                 goto out_tmp_free;
4377         }
4378
4379         werr = WERR_OK;
4380 out_tmp_free:
4381         talloc_free(tmp_ctx);
4382         return werr;
4383 }
4384
4385 /********************************************************************
4386  * construct_printer_info8
4387  * fill a spoolss_PrinterInfo8 struct
4388  ********************************************************************/
4389
4390 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4391                                       const struct spoolss_PrinterInfo2 *info2,
4392                                       const char *servername,
4393                                       struct spoolss_DeviceModeInfo *r,
4394                                       int snum)
4395 {
4396         WERROR result;
4397         const char *printername;
4398
4399         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4400         if (!W_ERROR_IS_OK(result)) {
4401                 return result;
4402         }
4403
4404         if (info2->devmode != NULL) {
4405                 result = copy_devicemode(mem_ctx,
4406                                          info2->devmode,
4407                                          &r->devmode);
4408                 if (!W_ERROR_IS_OK(result)) {
4409                         return result;
4410                 }
4411         } else if (lp_default_devmode(snum)) {
4412                 result = spoolss_create_default_devmode(mem_ctx,
4413                                                         info2->printername,
4414                                                         &r->devmode);
4415                 if (!W_ERROR_IS_OK(result)) {
4416                         return result;
4417                 }
4418         } else {
4419                 r->devmode = NULL;
4420                 DEBUG(8,("Returning NULL Devicemode!\n"));
4421         }
4422
4423         compose_devicemode_devicename(r->devmode, printername);
4424
4425         return WERR_OK;
4426 }
4427
4428 /********************************************************************
4429  Spoolss_enumprinters.
4430 ********************************************************************/
4431
4432 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4433                                            const struct auth_session_info *session_info,
4434                                            struct messaging_context *msg_ctx,
4435                                            const char *servername,
4436                                            uint32_t level,
4437                                            uint32_t flags,
4438                                            union spoolss_PrinterInfo **info_p,
4439                                            uint32_t *count_p)
4440 {
4441         int snum;
4442         int n_services;
4443         union spoolss_PrinterInfo *info = NULL;
4444         uint32_t count = 0;
4445         WERROR result = WERR_OK;
4446         struct dcerpc_binding_handle *b = NULL;
4447         TALLOC_CTX *tmp_ctx = NULL;
4448
4449         tmp_ctx = talloc_new(mem_ctx);
4450         if (!tmp_ctx) {
4451                 return WERR_NOT_ENOUGH_MEMORY;
4452         }
4453
4454         /*
4455          * printer shares are updated on client enumeration. The background
4456          * printer process updates printer_list.tdb at regular intervals.
4457          */
4458         become_root();
4459         delete_and_reload_printers();
4460         unbecome_root();
4461
4462         n_services = lp_numservices();
4463         *count_p = 0;
4464         *info_p = NULL;
4465
4466         for (snum = 0; snum < n_services; snum++) {
4467
4468                 const char *printer;
4469                 struct spoolss_PrinterInfo2 *info2;
4470
4471                 if (!snum_is_shared_printer(snum)) {
4472                         continue;
4473                 }
4474
4475                 printer = lp_const_servicename(snum);
4476
4477                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4478                         printer, snum));
4479
4480                 if (b == NULL) {
4481                         result = winreg_printer_binding_handle(tmp_ctx,
4482                                                                session_info,
4483                                                                msg_ctx,
4484                                                                &b);
4485                         if (!W_ERROR_IS_OK(result)) {
4486                                 goto out;
4487                         }
4488                 }
4489
4490                 result = winreg_create_printer(tmp_ctx, b,
4491                                                printer);
4492                 if (!W_ERROR_IS_OK(result)) {
4493                         goto out;
4494                 }
4495
4496                 info = talloc_realloc(tmp_ctx, info,
4497                                             union spoolss_PrinterInfo,
4498                                             count + 1);
4499                 if (!info) {
4500                         result = WERR_NOT_ENOUGH_MEMORY;
4501                         goto out;
4502                 }
4503
4504                 result = winreg_get_printer(tmp_ctx, b,
4505                                             printer, &info2);
4506                 if (!W_ERROR_IS_OK(result)) {
4507                         goto out;
4508                 }
4509
4510                 switch (level) {
4511                 case 0:
4512                         result = construct_printer_info0(info, session_info,
4513                                                          msg_ctx, info2,
4514                                                          servername,
4515                                                          &info[count].info0, snum);
4516                         break;
4517                 case 1:
4518                         result = construct_printer_info1(info, info2, flags,
4519                                                          servername,
4520                                                          &info[count].info1, snum);
4521                         break;
4522                 case 2:
4523                         result = construct_printer_info2(info, msg_ctx, info2,
4524                                                          servername,
4525                                                          &info[count].info2, snum);
4526                         break;
4527                 case 4:
4528                         result = construct_printer_info4(info, info2,
4529                                                          servername,
4530                                                          &info[count].info4, snum);
4531                         break;
4532                 case 5:
4533                         result = construct_printer_info5(info, info2,
4534                                                          servername,
4535                                                          &info[count].info5, snum);
4536                         break;
4537
4538                 default:
4539                         result = WERR_INVALID_LEVEL;
4540                         goto out;
4541                 }
4542
4543                 if (!W_ERROR_IS_OK(result)) {
4544                         goto out;
4545                 }
4546
4547                 count++;
4548         }
4549
4550 out:
4551         if (W_ERROR_IS_OK(result)) {
4552                 *info_p = talloc_move(mem_ctx, &info);
4553                 *count_p = count;
4554         }
4555
4556         talloc_free(tmp_ctx);
4557
4558         return result;
4559 }
4560
4561 /********************************************************************
4562  * handle enumeration of printers at level 0
4563  ********************************************************************/
4564
4565 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4566                                   const struct auth_session_info *session_info,
4567                                   struct messaging_context *msg_ctx,
4568                                   uint32_t flags,
4569                                   const char *servername,
4570                                   union spoolss_PrinterInfo **info,
4571                                   uint32_t *count)
4572 {
4573         DEBUG(4,("enum_all_printers_info_0\n"));
4574
4575         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4576                                             servername, 0, flags, info, count);
4577 }
4578
4579
4580 /********************************************************************
4581 ********************************************************************/
4582
4583 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4584                                        const struct auth_session_info *session_info,
4585                                        struct messaging_context *msg_ctx,
4586                                        const char *servername,
4587                                        uint32_t flags,
4588                                        union spoolss_PrinterInfo **info,
4589                                        uint32_t *count)
4590 {
4591         DEBUG(4,("enum_all_printers_info_1\n"));
4592
4593         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4594                                             servername, 1, flags, info, count);
4595 }
4596
4597 /********************************************************************
4598  enum_all_printers_info_1_local.
4599 *********************************************************************/
4600
4601 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4602                                              const struct auth_session_info *session_info,
4603                                              struct messaging_context *msg_ctx,
4604                                              const char *servername,
4605                                              union spoolss_PrinterInfo **info,
4606                                              uint32_t *count)
4607 {
4608         DEBUG(4,("enum_all_printers_info_1_local\n"));
4609
4610         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4611                                         servername, PRINTER_ENUM_ICON8, info, count);
4612 }
4613
4614 /********************************************************************
4615  enum_all_printers_info_1_name.
4616 *********************************************************************/
4617
4618 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4619                                             const struct auth_session_info *session_info,
4620                                             struct messaging_context *msg_ctx,
4621                                             const char *servername,
4622                                             union spoolss_PrinterInfo **info,
4623                                             uint32_t *count)
4624 {
4625         const char *s = servername;
4626
4627         DEBUG(4,("enum_all_printers_info_1_name\n"));
4628
4629         if (servername != NULL &&
4630             (servername[0] == '\\') && (servername[1] == '\\')) {
4631                 s = servername + 2;
4632         }
4633
4634         if (!is_myname_or_ipaddr(s)) {
4635                 return WERR_INVALID_NAME;
4636         }
4637
4638         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4639                                         servername, PRINTER_ENUM_ICON8, info, count);
4640 }
4641
4642 /********************************************************************
4643  enum_all_printers_info_1_network.
4644 *********************************************************************/
4645
4646 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4647                                                const struct auth_session_info *session_info,
4648                                                struct messaging_context *msg_ctx,
4649                                                const char *servername,
4650                                                union spoolss_PrinterInfo **info,
4651                                                uint32_t *count)
4652 {
4653         const char *s = servername;
4654
4655         DEBUG(4,("enum_all_printers_info_1_network\n"));
4656
4657         /* If we respond to a enum_printers level 1 on our name with flags
4658            set to PRINTER_ENUM_REMOTE with a list of printers then these
4659            printers incorrectly appear in the APW browse list.
4660            Specifically the printers for the server appear at the workgroup
4661            level where all the other servers in the domain are
4662            listed. Windows responds to this call with a
4663            WERR_CAN_NOT_COMPLETE so we should do the same. */
4664
4665         if (servername != NULL &&
4666             (servername[0] == '\\') && (servername[1] == '\\')) {
4667                  s = servername + 2;
4668         }
4669
4670         if (is_myname_or_ipaddr(s)) {
4671                  return WERR_CAN_NOT_COMPLETE;
4672         }
4673
4674         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4675                                         servername, PRINTER_ENUM_NAME, info, count);
4676 }
4677
4678 /********************************************************************
4679  * api_spoolss_enumprinters
4680  *
4681  * called from api_spoolss_enumprinters (see this to understand)
4682  ********************************************************************/
4683
4684 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4685                                        const struct auth_session_info *session_info,
4686                                        struct messaging_context *msg_ctx,
4687                                        const char *servername,
4688                                        union spoolss_PrinterInfo **info,
4689                                        uint32_t *count)
4690 {
4691         DEBUG(4,("enum_all_printers_info_2\n"));
4692
4693         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4694                                             servername, 2, 0, info, count);
4695 }
4696
4697 /********************************************************************
4698  * handle enumeration of printers at level 1
4699  ********************************************************************/
4700
4701 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4702                                   const struct auth_session_info *session_info,
4703                                   struct messaging_context *msg_ctx,
4704                                   uint32_t flags,
4705                                   const char *servername,
4706                                   union spoolss_PrinterInfo **info,
4707                                   uint32_t *count)
4708 {
4709         /* Not all the flags are equals */
4710
4711         if (flags & PRINTER_ENUM_LOCAL) {
4712                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4713                                                       msg_ctx, servername, info, count);
4714         }
4715
4716         if (flags & PRINTER_ENUM_NAME) {
4717                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4718                                                      msg_ctx, servername, info,
4719                                                      count);
4720         }
4721
4722         if (flags & PRINTER_ENUM_NETWORK) {
4723                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4724                                                         msg_ctx, servername, info,
4725                                                         count);
4726         }
4727
4728         return WERR_OK; /* NT4sp5 does that */
4729 }
4730
4731 /********************************************************************
4732  * handle enumeration of printers at level 2
4733  ********************************************************************/
4734
4735 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4736                                   const struct auth_session_info *session_info,
4737                                   struct messaging_context *msg_ctx,
4738                                   uint32_t flags,
4739                                   const char *servername,
4740                                   union spoolss_PrinterInfo **info,
4741                                   uint32_t *count)
4742 {
4743         if (flags & PRINTER_ENUM_LOCAL) {
4744
4745                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4746                                                 servername,
4747                                                 info, count);
4748         }
4749
4750         if (flags & PRINTER_ENUM_NAME) {
4751                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4752                         return WERR_INVALID_NAME;
4753                 }
4754
4755                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4756                                                 servername,
4757                                                 info, count);
4758         }
4759
4760         if (flags & PRINTER_ENUM_REMOTE) {
4761                 return WERR_INVALID_LEVEL;
4762         }
4763
4764         return WERR_OK;
4765 }
4766
4767 /********************************************************************
4768  * handle enumeration of printers at level 4
4769  ********************************************************************/
4770
4771 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4772                                   const struct auth_session_info *session_info,
4773                                   struct messaging_context *msg_ctx,
4774                                   uint32_t flags,
4775                                   const char *servername,
4776                                   union spoolss_PrinterInfo **info,
4777                                   uint32_t *count)
4778 {
4779         DEBUG(4,("enum_all_printers_info_4\n"));
4780
4781         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4782                                             servername, 4, flags, info, count);
4783 }
4784
4785
4786 /********************************************************************
4787  * handle enumeration of printers at level 5
4788  ********************************************************************/
4789
4790 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4791                                   const struct auth_session_info *session_info,
4792                                   struct messaging_context *msg_ctx,
4793                                   uint32_t flags,
4794                                   const char *servername,
4795                                   union spoolss_PrinterInfo **info,
4796                                   uint32_t *count)
4797 {
4798         DEBUG(4,("enum_all_printers_info_5\n"));
4799
4800         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4801                                             servername, 5, flags, info, count);
4802 }
4803
4804 /****************************************************************
4805  _spoolss_EnumPrinters
4806 ****************************************************************/
4807
4808 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4809                              struct spoolss_EnumPrinters *r)
4810 {
4811         const struct auth_session_info *session_info = get_session_info_system();
4812         WERROR result;
4813
4814         /* that's an [in out] buffer */
4815
4816         if (!r->in.buffer && (r->in.offered != 0)) {
4817                 return WERR_INVALID_PARAMETER;
4818         }
4819
4820         DEBUG(4,("_spoolss_EnumPrinters\n"));
4821
4822         *r->out.needed = 0;
4823         *r->out.count = 0;
4824         *r->out.info = NULL;
4825
4826         /*
4827          * Level 1:
4828          *          flags==PRINTER_ENUM_NAME
4829          *           if name=="" then enumerates all printers
4830          *           if name!="" then enumerate the printer
4831          *          flags==PRINTER_ENUM_REMOTE
4832          *          name is NULL, enumerate printers
4833          * Level 2: name!="" enumerates printers, name can't be NULL
4834          * Level 3: doesn't exist
4835          * Level 4: does a local registry lookup
4836          * Level 5: same as Level 2
4837          */
4838
4839         if (r->in.server && r->in.server[0] == '\0') {
4840                 r->in.server = NULL;
4841         }
4842
4843         switch (r->in.level) {
4844         case 0:
4845                 result = enumprinters_level0(p->mem_ctx, session_info,
4846                                              p->msg_ctx, r->in.flags,
4847                                              r->in.server,
4848                                              r->out.info, r->out.count);
4849                 break;
4850         case 1:
4851                 result = enumprinters_level1(p->mem_ctx, session_info,
4852                                              p->msg_ctx, r->in.flags,
4853                                              r->in.server,
4854                                              r->out.info, r->out.count);
4855                 break;
4856         case 2:
4857                 result = enumprinters_level2(p->mem_ctx, session_info,
4858                                              p->msg_ctx, r->in.flags,
4859                                              r->in.server,
4860                                              r->out.info, r->out.count);
4861                 break;
4862         case 4:
4863                 result = enumprinters_level4(p->mem_ctx, session_info,
4864                                              p->msg_ctx, r->in.flags,
4865                                              r->in.server,
4866                                              r->out.info, r->out.count);
4867                 break;
4868         case 5:
4869                 result = enumprinters_level5(p->mem_ctx, session_info,
4870                                              p->msg_ctx, r->in.flags,
4871                                              r->in.server,
4872                                              r->out.info, r->out.count);
4873                 break;
4874         default:
4875                 return WERR_INVALID_LEVEL;
4876         }
4877
4878         if (!W_ERROR_IS_OK(result)) {
4879                 return result;
4880         }
4881
4882         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4883                                                      spoolss_EnumPrinters,
4884                                                      *r->out.info, r->in.level,
4885                                                      *r->out.count);
4886         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4887         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4888
4889         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4890 }
4891
4892 /****************************************************************
4893  _spoolss_GetPrinter
4894 ****************************************************************/
4895
4896 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4897                            struct spoolss_GetPrinter *r)
4898 {
4899         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4900         struct spoolss_PrinterInfo2 *info2 = NULL;
4901         WERROR result = WERR_OK;
4902         int snum;
4903
4904         /* that's an [in out] buffer */
4905
4906         if (!r->in.buffer && (r->in.offered != 0)) {
4907                 result = WERR_INVALID_PARAMETER;
4908                 goto err_info_free;
4909         }
4910
4911         *r->out.needed = 0;
4912
4913         if (Printer == NULL) {
4914                 result = WERR_INVALID_HANDLE;
4915                 goto err_info_free;
4916         }
4917
4918         if (Printer->printer_type == SPLHND_SERVER) {
4919
4920                 struct dcerpc_binding_handle *b;
4921
4922                 if (r->in.level != 3) {
4923                         result = WERR_INVALID_LEVEL;
4924                         goto err_info_free;
4925                 }
4926
4927                 result = winreg_printer_binding_handle(p->mem_ctx,
4928                                                        get_session_info_system(),
4929                                                        p->msg_ctx,
4930                                                        &b);
4931                 if (!W_ERROR_IS_OK(result)) {
4932                         goto err_info_free;
4933                 }
4934
4935                 result = winreg_get_printserver_secdesc(p->mem_ctx,
4936                                                         b,
4937                                                         &r->out.info->info3.secdesc);
4938                 if (!W_ERROR_IS_OK(result)) {
4939                         goto err_info_free;
4940                 }
4941
4942                 goto done;
4943         }
4944
4945         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4946                 result = WERR_INVALID_HANDLE;
4947                 goto err_info_free;
4948         }
4949
4950         result = winreg_get_printer_internal(p->mem_ctx,
4951                                     get_session_info_system(),
4952                                     p->msg_ctx,
4953                                     lp_const_servicename(snum),
4954                                     &info2);
4955         if (!W_ERROR_IS_OK(result)) {
4956                 goto err_info_free;
4957         }
4958
4959         switch (r->in.level) {
4960         case 0:
4961                 result = construct_printer_info0(p->mem_ctx,
4962                                                  get_session_info_system(),
4963                                                  p->msg_ctx,
4964                                                  info2,
4965                                                  Printer->servername,
4966                                                  &r->out.info->info0,
4967                                                  snum);
4968                 break;
4969         case 1:
4970                 result = construct_printer_info1(p->mem_ctx, info2,
4971                                                  PRINTER_ENUM_ICON8,
4972                                                  Printer->servername,
4973                                                  &r->out.info->info1, snum);
4974                 break;
4975         case 2:
4976                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4977                                                  Printer->servername,
4978                                                  &r->out.info->info2, snum);
4979                 break;
4980         case 3:
4981                 result = construct_printer_info3(p->mem_ctx, info2,
4982                                                  Printer->servername,
4983                                                  &r->out.info->info3, snum);
4984                 break;
4985         case 4:
4986                 result = construct_printer_info4(p->mem_ctx, info2,
4987                                                  Printer->servername,
4988                                                  &r->out.info->info4, snum);
4989                 break;
4990         case 5:
4991                 result = construct_printer_info5(p->mem_ctx, info2,
4992                                                  Printer->servername,
4993                                                  &r->out.info->info5, snum);
4994                 break;
4995         case 6:
4996                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4997                                                  Printer->servername,
4998                                                  &r->out.info->info6, snum);
4999                 break;
5000         case 7:
5001                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
5002                                                  Printer->servername,
5003                                                  &r->out.info->info7, snum);
5004                 break;
5005         case 8:
5006                 result = construct_printer_info8(p->mem_ctx, info2,
5007                                                  Printer->servername,
5008                                                  &r->out.info->info8, snum);
5009                 break;
5010         default:
5011                 result = WERR_INVALID_LEVEL;
5012                 break;
5013         }
5014         TALLOC_FREE(info2);
5015
5016         if (!W_ERROR_IS_OK(result)) {
5017                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
5018                           r->in.level, win_errstr(result)));
5019                 goto err_info_free;
5020         }
5021  done:
5022         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
5023                                                r->out.info, r->in.level);
5024         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5025
5026         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5027
5028 err_info_free:
5029         TALLOC_FREE(r->out.info);
5030         return result;
5031 }
5032
5033 /********************************************************************
5034  ********************************************************************/
5035
5036 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
5037         do { \
5038                 if (in && strlen(in)) { \
5039                         out = talloc_strdup(mem_ctx, in); \
5040                 } else { \
5041                         out = talloc_strdup(mem_ctx, ""); \
5042                 } \
5043                 W_ERROR_HAVE_NO_MEMORY(out); \
5044         } while (0);
5045
5046 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
5047         do { \
5048                 if (in && strlen(in)) { \
5049                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
5050                 } else { \
5051                         out = talloc_strdup(mem_ctx, ""); \
5052                 } \
5053                 W_ERROR_HAVE_NO_MEMORY(out); \
5054         } while (0);
5055
5056 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
5057                                                   const char **string_array,
5058                                                   const char ***presult,
5059                                                   const char *cservername,
5060                                                   const char *arch,
5061                                                   int version)
5062 {
5063         size_t i;
5064         size_t num_strings = 0;
5065         const char **array = NULL;
5066
5067         if (string_array == NULL) {
5068                 return WERR_INVALID_PARAMETER;
5069         }
5070
5071         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
5072                 const char *str = NULL;
5073
5074                 if (cservername == NULL || arch == NULL) {
5075                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
5076                 } else {
5077                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
5078                 }
5079
5080                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5081                         TALLOC_FREE(array);
5082                         return WERR_NOT_ENOUGH_MEMORY;
5083                 }
5084         }
5085
5086         if (i > 0) {
5087                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5088                              &array, &num_strings);
5089         }
5090
5091         if (presult != NULL) {
5092                 *presult = array;
5093         } else {
5094                 talloc_free(array);
5095         }
5096
5097         return WERR_OK;
5098 }
5099
5100 /********************************************************************
5101  * fill a spoolss_DriverInfo1 struct
5102  ********************************************************************/
5103
5104 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5105                                         struct spoolss_DriverInfo1 *r,
5106                                         const struct spoolss_DriverInfo8 *driver,
5107                                         const char *servername)
5108 {
5109         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5110         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5111
5112         return WERR_OK;
5113 }
5114
5115 /********************************************************************
5116  * fill a spoolss_DriverInfo2 struct
5117  ********************************************************************/
5118
5119 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5120                                         struct spoolss_DriverInfo2 *r,
5121                                         const struct spoolss_DriverInfo8 *driver,
5122                                         const char *servername)
5123
5124 {
5125         const char *cservername = canon_servername(servername);
5126
5127         r->version              = driver->version;
5128
5129         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5130         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5131         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5132         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5133
5134         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5135                                driver->architecture,
5136                                driver->version,
5137                                driver->driver_path,
5138                                r->driver_path);
5139
5140         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5141                                driver->architecture,
5142                                driver->version,
5143                                driver->data_file,
5144                                r->data_file);
5145
5146         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5147                                driver->architecture,
5148                                driver->version,
5149                                driver->config_file,
5150                                r->config_file);
5151
5152         return WERR_OK;
5153 }
5154
5155 /********************************************************************
5156  * fill a spoolss_DriverInfo3 struct
5157  ********************************************************************/
5158
5159 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5160                                         struct spoolss_DriverInfo3 *r,
5161                                         const struct spoolss_DriverInfo8 *driver,
5162                                         const char *servername)
5163 {
5164         const char *cservername = canon_servername(servername);
5165
5166         r->version              = driver->version;
5167
5168         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5169         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5170         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5171         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5172
5173         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5174                                driver->architecture,
5175                                driver->version,
5176                                driver->driver_path,
5177                                r->driver_path);
5178
5179         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5180                                driver->architecture,
5181                                driver->version,
5182                                driver->data_file,
5183                                r->data_file);
5184
5185         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5186                                driver->architecture,
5187                                driver->version,
5188                                driver->config_file,
5189                                r->config_file);
5190
5191         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5192                                driver->architecture,
5193                                driver->version,
5194                                driver->help_file,
5195                                r->help_file);
5196
5197         FILL_DRIVER_STRING(mem_ctx,
5198                            driver->monitor_name,
5199                            r->monitor_name);
5200
5201         FILL_DRIVER_STRING(mem_ctx,
5202                            driver->default_datatype,
5203                            r->default_datatype);
5204
5205         return string_array_from_driver_info(mem_ctx,
5206                                              driver->dependent_files,
5207                                              &r->dependent_files,
5208                                              cservername,
5209                                              driver->architecture,
5210                                              driver->version);
5211 }
5212
5213 /********************************************************************
5214  * fill a spoolss_DriverInfo4 struct
5215  ********************************************************************/
5216
5217 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5218                                         struct spoolss_DriverInfo4 *r,
5219                                         const struct spoolss_DriverInfo8 *driver,
5220                                         const char *servername)
5221 {
5222         const char *cservername = canon_servername(servername);
5223         WERROR result;
5224
5225         r->version              = driver->version;
5226
5227         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5228         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5229         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5230         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5231
5232         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5233                                driver->architecture,
5234                                driver->version,
5235                                driver->driver_path,
5236                                r->driver_path);
5237
5238         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5239                                driver->architecture,
5240                                driver->version,
5241                                driver->data_file,
5242                                r->data_file);
5243
5244         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5245                                driver->architecture,
5246                                driver->version,
5247                                driver->config_file,
5248                                r->config_file);
5249
5250         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5251                                driver->architecture,
5252                                driver->version,
5253                                driver->help_file,
5254                                r->help_file);
5255
5256         result = string_array_from_driver_info(mem_ctx,
5257                                                driver->dependent_files,
5258                                                &r->dependent_files,
5259                                                cservername,
5260                                                driver->architecture,
5261                                                driver->version);
5262         if (!W_ERROR_IS_OK(result)) {
5263                 return result;
5264         }
5265
5266         FILL_DRIVER_STRING(mem_ctx,
5267                            driver->monitor_name,
5268                            r->monitor_name);
5269
5270         FILL_DRIVER_STRING(mem_ctx,
5271                            driver->default_datatype,
5272                            r->default_datatype);
5273
5274
5275         result = string_array_from_driver_info(mem_ctx,
5276                                                driver->previous_names,
5277                                                &r->previous_names,
5278                                                NULL, NULL, 0);
5279
5280         return result;
5281 }
5282
5283 /********************************************************************
5284  * fill a spoolss_DriverInfo5 struct
5285  ********************************************************************/
5286
5287 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5288                                         struct spoolss_DriverInfo5 *r,
5289                                         const struct spoolss_DriverInfo8 *driver,
5290                                         const char *servername)
5291 {
5292         const char *cservername = canon_servername(servername);
5293
5294         r->version              = driver->version;
5295
5296         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5297         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5298         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5299         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5300
5301         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5302                                driver->architecture,
5303                                driver->version,
5304                                driver->driver_path,
5305                                r->driver_path);
5306
5307         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5308                                driver->architecture,
5309                                driver->version,
5310                                driver->data_file,
5311                                r->data_file);
5312
5313         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5314                                driver->architecture,
5315                                driver->version,
5316                                driver->config_file,
5317                                r->config_file);
5318
5319         r->driver_attributes    = 0;
5320         r->config_version       = 0;
5321         r->driver_version       = 0;
5322
5323         return WERR_OK;
5324 }
5325 /********************************************************************
5326  * fill a spoolss_DriverInfo6 struct
5327  ********************************************************************/
5328
5329 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5330                                         struct spoolss_DriverInfo6 *r,
5331                                         const struct spoolss_DriverInfo8 *driver,
5332                                         const char *servername)
5333 {
5334         const char *cservername = canon_servername(servername);
5335         WERROR result;
5336
5337         r->version              = driver->version;
5338
5339         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5340         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5341         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5342         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5343
5344         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5345                                driver->architecture,
5346                                driver->version,
5347                                driver->driver_path,
5348                                r->driver_path);
5349
5350         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5351                                driver->architecture,
5352                                driver->version,
5353                                driver->data_file,
5354                                r->data_file);
5355
5356         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5357                                driver->architecture,
5358                                driver->version,
5359                                driver->config_file,
5360                                r->config_file);
5361
5362         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5363                                driver->architecture,
5364                                driver->version,
5365                                driver->help_file,
5366                                r->help_file);
5367
5368         FILL_DRIVER_STRING(mem_ctx,
5369                            driver->monitor_name,
5370                            r->monitor_name);
5371
5372         FILL_DRIVER_STRING(mem_ctx,
5373                            driver->default_datatype,
5374                            r->default_datatype);
5375
5376         result = string_array_from_driver_info(mem_ctx,
5377                                                driver->dependent_files,
5378                                                &r->dependent_files,
5379                                                cservername,
5380                                                driver->architecture,
5381                                                driver->version);
5382         if (!W_ERROR_IS_OK(result)) {
5383                 return result;
5384         }
5385
5386         result = string_array_from_driver_info(mem_ctx,
5387                                                driver->previous_names,
5388                                                &r->previous_names,
5389                                                NULL, NULL, 0);
5390         if (!W_ERROR_IS_OK(result)) {
5391                 return result;
5392         }
5393
5394         r->driver_date          = driver->driver_date;
5395         r->driver_version       = driver->driver_version;
5396
5397         FILL_DRIVER_STRING(mem_ctx,
5398                            driver->manufacturer_name,
5399                            r->manufacturer_name);
5400         FILL_DRIVER_STRING(mem_ctx,
5401                            driver->manufacturer_url,
5402                            r->manufacturer_url);
5403         FILL_DRIVER_STRING(mem_ctx,
5404                            driver->hardware_id,
5405                            r->hardware_id);
5406         FILL_DRIVER_STRING(mem_ctx,
5407                            driver->provider,
5408                            r->provider);
5409
5410         return WERR_OK;
5411 }
5412
5413 /********************************************************************
5414  * fill a spoolss_DriverInfo8 struct
5415  ********************************************************************/
5416
5417 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5418                                         struct spoolss_DriverInfo8 *r,
5419                                         const struct spoolss_DriverInfo8 *driver,
5420                                         const char *servername)
5421 {
5422         const char *cservername = canon_servername(servername);
5423         WERROR result;
5424
5425         r->version              = driver->version;
5426
5427         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5428         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5429         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5430         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5431
5432         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5433                                driver->architecture,
5434                                driver->version,
5435                                driver->driver_path,
5436                                r->driver_path);
5437
5438         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5439                                driver->architecture,
5440                                driver->version,
5441                                driver->data_file,
5442                                r->data_file);
5443
5444         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5445                                driver->architecture,
5446                                driver->version,
5447                                driver->config_file,
5448                                r->config_file);
5449
5450         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5451                                driver->architecture,
5452                                driver->version,
5453                                driver->help_file,
5454                                r->help_file);
5455
5456         FILL_DRIVER_STRING(mem_ctx,
5457                            driver->monitor_name,
5458                            r->monitor_name);
5459
5460         FILL_DRIVER_STRING(mem_ctx,
5461                            driver->default_datatype,
5462                            r->default_datatype);
5463
5464         result = string_array_from_driver_info(mem_ctx,
5465                                                driver->dependent_files,
5466                                                &r->dependent_files,
5467                                                cservername,
5468                                                driver->architecture,
5469                                                driver->version);
5470         if (!W_ERROR_IS_OK(result)) {
5471                 return result;
5472         }
5473
5474         result = string_array_from_driver_info(mem_ctx,
5475                                                driver->previous_names,
5476                                                &r->previous_names,
5477                                                NULL, NULL, 0);
5478         if (!W_ERROR_IS_OK(result)) {
5479                 return result;
5480         }
5481
5482         r->driver_date          = driver->driver_date;
5483         r->driver_version       = driver->driver_version;
5484
5485         FILL_DRIVER_STRING(mem_ctx,
5486                            driver->manufacturer_name,
5487                            r->manufacturer_name);
5488         FILL_DRIVER_STRING(mem_ctx,
5489                            driver->manufacturer_url,
5490                            r->manufacturer_url);
5491         FILL_DRIVER_STRING(mem_ctx,
5492                            driver->hardware_id,
5493                            r->hardware_id);
5494         FILL_DRIVER_STRING(mem_ctx,
5495                            driver->provider,
5496                            r->provider);
5497
5498         FILL_DRIVER_STRING(mem_ctx,
5499                            driver->print_processor,
5500                            r->print_processor);
5501         FILL_DRIVER_STRING(mem_ctx,
5502                            driver->vendor_setup,
5503                            r->vendor_setup);
5504
5505         result = string_array_from_driver_info(mem_ctx,
5506                                                driver->color_profiles,
5507                                                &r->color_profiles,
5508                                                NULL, NULL, 0);
5509         if (!W_ERROR_IS_OK(result)) {
5510                 return result;
5511         }
5512
5513         FILL_DRIVER_STRING(mem_ctx,
5514                            driver->inf_path,
5515                            r->inf_path);
5516
5517         r->printer_driver_attributes    = driver->printer_driver_attributes;
5518
5519         result = string_array_from_driver_info(mem_ctx,
5520                                                driver->core_driver_dependencies,
5521                                                &r->core_driver_dependencies,
5522                                                NULL, NULL, 0);
5523         if (!W_ERROR_IS_OK(result)) {
5524                 return result;
5525         }
5526
5527         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5528         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5529
5530         return WERR_OK;
5531 }
5532
5533 #if 0 /* disabled until marshalling issues are resolved - gd */
5534 /********************************************************************
5535  ********************************************************************/
5536
5537 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5538                                           struct spoolss_DriverFileInfo *r,
5539                                           const char *cservername,
5540                                           const char *file_name,
5541                                           enum spoolss_DriverFileType file_type,
5542                                           uint32_t file_version)
5543 {
5544         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5545                                           cservername, file_name);
5546         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5547         r->file_type    = file_type;
5548         r->file_version = file_version;
5549
5550         return WERR_OK;
5551 }
5552
5553 /********************************************************************
5554  ********************************************************************/
5555
5556 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5557                                                  const struct spoolss_DriverInfo8 *driver,
5558                                                  const char *cservername,
5559                                                  struct spoolss_DriverFileInfo **info_p,
5560                                                  uint32_t *count_p)
5561 {
5562         struct spoolss_DriverFileInfo *info = NULL;
5563         uint32_t count = 0;
5564         WERROR result;
5565         uint32_t i;
5566
5567         *info_p = NULL;
5568         *count_p = 0;
5569
5570         if (strlen(driver->driver_path)) {
5571                 info = talloc_realloc(mem_ctx, info,
5572                                             struct spoolss_DriverFileInfo,
5573                                             count + 1);
5574                 W_ERROR_HAVE_NO_MEMORY(info);
5575                 result = fill_spoolss_DriverFileInfo(info,
5576                                                      &info[count],
5577                                                      cservername,
5578                                                      driver->driver_path,
5579                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5580                                                      0);
5581                 W_ERROR_NOT_OK_RETURN(result);
5582                 count++;
5583         }
5584
5585         if (strlen(driver->config_file)) {
5586                 info = talloc_realloc(mem_ctx, info,
5587                                             struct spoolss_DriverFileInfo,
5588                                             count + 1);
5589                 W_ERROR_HAVE_NO_MEMORY(info);
5590                 result = fill_spoolss_DriverFileInfo(info,
5591                                                      &info[count],
5592                                                      cservername,
5593                                                      driver->config_file,
5594                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5595                                                      0);
5596                 W_ERROR_NOT_OK_RETURN(result);
5597                 count++;
5598         }
5599
5600         if (strlen(driver->data_file)) {
5601                 info = talloc_realloc(mem_ctx, info,
5602                                             struct spoolss_DriverFileInfo,
5603                                             count + 1);
5604                 W_ERROR_HAVE_NO_MEMORY(info);
5605                 result = fill_spoolss_DriverFileInfo(info,
5606                                                      &info[count],
5607                                                      cservername,
5608                                                      driver->data_file,
5609                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5610                                                      0);
5611                 W_ERROR_NOT_OK_RETURN(result);
5612                 count++;
5613         }
5614
5615         if (strlen(driver->help_file)) {
5616                 info = talloc_realloc(mem_ctx, info,
5617                                             struct spoolss_DriverFileInfo,
5618                                             count + 1);
5619                 W_ERROR_HAVE_NO_MEMORY(info);
5620                 result = fill_spoolss_DriverFileInfo(info,
5621                                                      &info[count],
5622                                                      cservername,
5623                                                      driver->help_file,
5624                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5625                                                      0);
5626                 W_ERROR_NOT_OK_RETURN(result);
5627                 count++;
5628         }
5629
5630         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5631                 info = talloc_realloc(mem_ctx, info,
5632                                             struct spoolss_DriverFileInfo,
5633                                             count + 1);
5634                 W_ERROR_HAVE_NO_MEMORY(info);
5635                 result = fill_spoolss_DriverFileInfo(info,
5636                                                      &info[count],
5637                                                      cservername,
5638                                                      driver->dependent_files[i],
5639                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5640                                                      0);
5641                 W_ERROR_NOT_OK_RETURN(result);
5642                 count++;
5643         }
5644
5645         *info_p = info;
5646         *count_p = count;
5647
5648         return WERR_OK;
5649 }
5650
5651 /********************************************************************
5652  * fill a spoolss_DriverInfo101 struct
5653  ********************************************************************/
5654
5655 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5656                                           struct spoolss_DriverInfo101 *r,
5657                                           const struct spoolss_DriverInfo8 *driver,
5658                                           const char *servername)
5659 {
5660         const char *cservername = canon_servername(servername);
5661         WERROR result;
5662
5663         r->version              = driver->version;
5664
5665         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5666         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5667         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5668         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5669
5670         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5671                                                     cservername,
5672                                                     &r->file_info,
5673                                                     &r->file_count);
5674         if (!W_ERROR_IS_OK(result)) {
5675                 return result;
5676         }
5677
5678         FILL_DRIVER_STRING(mem_ctx,
5679                            driver->monitor_name,
5680                            r->monitor_name);
5681
5682         FILL_DRIVER_STRING(mem_ctx,
5683                            driver->default_datatype,
5684                            r->default_datatype);
5685
5686         result = string_array_from_driver_info(mem_ctx,
5687                                                driver->previous_names,
5688                                                &r->previous_names,
5689                                                NULL, NULL, 0);
5690         if (!W_ERROR_IS_OK(result)) {
5691                 return result;
5692         }
5693
5694         r->driver_date          = driver->driver_date;
5695         r->driver_version       = driver->driver_version;
5696
5697         FILL_DRIVER_STRING(mem_ctx,
5698                            driver->manufacturer_name,
5699                            r->manufacturer_name);
5700         FILL_DRIVER_STRING(mem_ctx,
5701                            driver->manufacturer_url,
5702                            r->manufacturer_url);
5703         FILL_DRIVER_STRING(mem_ctx,
5704                            driver->hardware_id,
5705                            r->hardware_id);
5706         FILL_DRIVER_STRING(mem_ctx,
5707                            driver->provider,
5708                            r->provider);
5709
5710         return WERR_OK;
5711 }
5712 #endif
5713 /********************************************************************
5714  ********************************************************************/
5715
5716 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5717                                                   const struct auth_session_info *session_info,
5718                                                   struct messaging_context *msg_ctx,
5719                                                   uint32_t level,
5720                                                   union spoolss_DriverInfo *r,
5721                                                   int snum,
5722                                                   const char *servername,
5723                                                   const char *architecture,
5724                                                   uint32_t version)
5725 {
5726         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5727         struct spoolss_DriverInfo8 *driver;
5728         WERROR result;
5729         struct dcerpc_binding_handle *b;
5730         TALLOC_CTX *tmp_ctx = NULL;
5731
5732         if (level == 101) {
5733                 return WERR_INVALID_LEVEL;
5734         }
5735
5736         tmp_ctx = talloc_new(mem_ctx);
5737         if (!tmp_ctx) {
5738                 return WERR_NOT_ENOUGH_MEMORY;
5739         }
5740
5741         result = winreg_printer_binding_handle(tmp_ctx,
5742                                                session_info,
5743                                                msg_ctx,
5744                                                &b);
5745         if (!W_ERROR_IS_OK(result)) {
5746                 goto done;
5747         }
5748
5749         result = winreg_get_printer(tmp_ctx, b,
5750                                     lp_const_servicename(snum),
5751                                     &pinfo2);
5752         if (!W_ERROR_IS_OK(result)) {
5753                 DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
5754                         lp_const_servicename(snum), win_errstr(result));
5755                 result = WERR_INVALID_PRINTER_NAME;
5756                 goto done;
5757         }
5758
5759         if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
5760                 result = WERR_UNKNOWN_PRINTER_DRIVER;
5761                 goto done;
5762         }
5763
5764         DBG_INFO("Construct printer driver [%s] for [%s]\n",
5765                  pinfo2->drivername,
5766                  pinfo2->sharename);
5767
5768         result = winreg_get_driver(tmp_ctx, b,
5769                                    architecture,
5770                                    pinfo2->drivername, version, &driver);
5771
5772         DBG_INFO("winreg_get_driver() status: %s\n",
5773                  win_errstr(result));
5774
5775         if (!W_ERROR_IS_OK(result)) {
5776                 /*
5777                  * Is this a W2k client ?
5778                  */
5779
5780                 if (version < 3) {
5781                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5782                         goto done;
5783                 }
5784
5785                 /* Yes - try again with a WinNT driver. */
5786                 version = 2;
5787                 result = winreg_get_driver(tmp_ctx, b,
5788                                            architecture,
5789                                            pinfo2->drivername,
5790                                            version, &driver);
5791                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5792                         win_errstr(result)));
5793                 if (!W_ERROR_IS_OK(result)) {
5794                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5795                         goto done;
5796                 }
5797         }
5798
5799         /* these are allocated on mem_ctx and not tmp_ctx because they are
5800          * the 'return value' and need to outlive this call */
5801         switch (level) {
5802         case 1:
5803                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5804                 break;
5805         case 2:
5806                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5807                 break;
5808         case 3:
5809                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5810                 break;
5811         case 4:
5812                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5813                 break;
5814         case 5:
5815                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5816                 break;
5817         case 6:
5818                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5819                 break;
5820         case 8:
5821                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5822                 break;
5823 #if 0 /* disabled until marshalling issues are resolved - gd */
5824         case 101:
5825                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5826                 break;
5827 #endif
5828         default:
5829                 result = WERR_INVALID_LEVEL;
5830                 break;
5831         }
5832
5833 done:
5834         talloc_free(tmp_ctx);
5835         return result;
5836 }
5837
5838 /****************************************************************
5839  _spoolss_GetPrinterDriver2
5840 ****************************************************************/
5841
5842 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5843                                   struct spoolss_GetPrinterDriver2 *r)
5844 {
5845         struct printer_handle *printer;
5846         WERROR result;
5847         uint32_t version = r->in.client_major_version;
5848
5849         int snum;
5850
5851         /* that's an [in out] buffer */
5852
5853         if (!r->in.buffer && (r->in.offered != 0)) {
5854                 result = WERR_INVALID_PARAMETER;
5855                 goto err_info_free;
5856         }
5857
5858         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5859
5860         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5861                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5862                 result = WERR_INVALID_PRINTER_NAME;
5863                 goto err_info_free;
5864         }
5865
5866         *r->out.needed = 0;
5867         *r->out.server_major_version = 0;
5868         *r->out.server_minor_version = 0;
5869
5870         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5871                 result = WERR_INVALID_HANDLE;
5872                 goto err_info_free;
5873         }
5874
5875         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5876                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5877                         "downgrading to v3\n"));
5878                 version = SPOOLSS_DRIVER_VERSION_200X;
5879         }
5880
5881         result = construct_printer_driver_info_level(p->mem_ctx,
5882                                                      get_session_info_system(),
5883                                                      p->msg_ctx,
5884                                                      r->in.level, r->out.info,
5885                                                      snum, printer->servername,
5886                                                      r->in.architecture,
5887                                                      version);
5888         if (!W_ERROR_IS_OK(result)) {
5889                 goto err_info_free;
5890         }
5891
5892         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5893                                                r->out.info, r->in.level);
5894         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5895
5896         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5897
5898 err_info_free:
5899         TALLOC_FREE(r->out.info);
5900         return result;
5901 }
5902
5903
5904 /****************************************************************
5905  _spoolss_StartPagePrinter
5906 ****************************************************************/
5907
5908 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5909                                  struct spoolss_StartPagePrinter *r)
5910 {
5911         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5912
5913         if (!Printer) {
5914                 DEBUG(3,("_spoolss_StartPagePrinter: "
5915                         "Error in startpageprinter printer handle\n"));
5916                 return WERR_INVALID_HANDLE;
5917         }
5918
5919         Printer->page_started = true;
5920         return WERR_OK;
5921 }
5922
5923 /****************************************************************
5924  _spoolss_EndPagePrinter
5925 ****************************************************************/
5926
5927 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5928                                struct spoolss_EndPagePrinter *r)
5929 {
5930         int snum;
5931
5932         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5933
5934         if (!Printer) {
5935                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5936                         OUR_HANDLE(r->in.handle)));
5937                 return WERR_INVALID_HANDLE;
5938         }
5939
5940         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5941                 return WERR_INVALID_HANDLE;
5942
5943         Printer->page_started = false;
5944         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5945
5946         return WERR_OK;
5947 }
5948
5949 /****************************************************************
5950  _spoolss_StartDocPrinter
5951 ****************************************************************/
5952
5953 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5954                                 struct spoolss_StartDocPrinter *r)
5955 {
5956         struct dcesrv_call_state *dce_call = p->dce_call;
5957         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
5958         const struct tsocket_address *remote_address =
5959                 dcesrv_connection_get_remote_address(dcesrv_conn);
5960         struct auth_session_info *session_info =
5961                 dcesrv_call_session_info(dce_call);
5962         struct spoolss_DocumentInfo1 *info_1;
5963         int snum;
5964         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5965         WERROR werr;
5966         char *rhost;
5967         int rc;
5968
5969         if (!Printer) {
5970                 DEBUG(2,("_spoolss_StartDocPrinter: "
5971                         "Invalid handle (%s:%u:%u)\n",
5972                         OUR_HANDLE(r->in.handle)));
5973                 return WERR_INVALID_HANDLE;
5974         }
5975
5976         if (Printer->jobid) {
5977                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5978                           "StartDocPrinter called twice! "
5979                           "(existing jobid = %d)\n", Printer->jobid));
5980                 return WERR_INVALID_HANDLE;
5981         }
5982
5983         if (r->in.info_ctr->level != 1) {
5984                 return WERR_INVALID_LEVEL;
5985         }
5986
5987         info_1 = r->in.info_ctr->info.info1;
5988
5989         /*
5990          * a nice thing with NT is it doesn't listen to what you tell it.
5991          * when asked to send _only_ RAW data, it tries to send data
5992          * in EMF format.
5993          *
5994          * So I add checks like in NT Server ...
5995          */
5996
5997         if (info_1->datatype) {
5998                 /*
5999                  * The v4 driver model used in Windows 8 declares print jobs
6000                  * intended to bypass the XPS processing layer by setting
6001                  * datatype to "XPS_PASS" instead of "RAW".
6002                  */
6003                 if ((strcmp(info_1->datatype, "RAW") != 0)
6004                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
6005                         *r->out.job_id = 0;
6006                         return WERR_INVALID_DATATYPE;
6007                 }
6008         }
6009
6010         /* get the share number of the printer */
6011         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6012                 return WERR_INVALID_HANDLE;
6013         }
6014
6015         rc = get_remote_hostname(remote_address,
6016                                  &rhost,
6017                                  p->mem_ctx);
6018         if (rc < 0) {
6019                 return WERR_NOT_ENOUGH_MEMORY;
6020         }
6021         if (strequal(rhost,"UNKNOWN")) {
6022                 rhost = tsocket_address_inet_addr_string(remote_address,
6023                                                          p->mem_ctx);
6024                 if (rhost == NULL) {
6025                         return WERR_NOT_ENOUGH_MEMORY;
6026                 }
6027         }
6028
6029         werr = print_job_start(session_info,
6030                                p->msg_ctx,
6031                                rhost,
6032                                snum,
6033                                info_1->document_name,
6034                                info_1->output_file,
6035                                Printer->devmode,
6036                                &Printer->jobid);
6037
6038         /* An error occurred in print_job_start() so return an appropriate
6039            NT error code. */
6040
6041         if (!W_ERROR_IS_OK(werr)) {
6042                 return werr;
6043         }
6044
6045         Printer->document_started = true;
6046         *r->out.job_id = Printer->jobid;
6047
6048         return WERR_OK;
6049 }
6050
6051 /****************************************************************
6052  _spoolss_EndDocPrinter
6053 ****************************************************************/
6054
6055 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
6056                               struct spoolss_EndDocPrinter *r)
6057 {
6058         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6059         NTSTATUS status;
6060         int snum;
6061
6062         if (!Printer) {
6063                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
6064                         OUR_HANDLE(r->in.handle)));
6065                 return WERR_INVALID_HANDLE;
6066         }
6067
6068         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6069                 return WERR_INVALID_HANDLE;
6070         }
6071
6072         Printer->document_started = false;
6073         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
6074         if (!NT_STATUS_IS_OK(status)) {
6075                 DEBUG(2, ("_spoolss_EndDocPrinter: "
6076                           "print_job_end failed [%s]\n",
6077                           nt_errstr(status)));
6078         }
6079
6080         Printer->jobid = 0;
6081         return ntstatus_to_werror(status);
6082 }
6083
6084 /****************************************************************
6085  _spoolss_WritePrinter
6086 ****************************************************************/
6087
6088 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
6089                              struct spoolss_WritePrinter *r)
6090 {
6091         ssize_t buffer_written;
6092         int snum;
6093         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6094
6095         if (!Printer) {
6096                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6097                         OUR_HANDLE(r->in.handle)));
6098                 *r->out.num_written = r->in._data_size;
6099                 return WERR_INVALID_HANDLE;
6100         }
6101
6102         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6103                 return WERR_INVALID_HANDLE;
6104
6105         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
6106         buffer_written = print_job_write(global_event_context(),p->msg_ctx,
6107                                                    snum, Printer->jobid,
6108                                                    (const char *)r->in.data.data,
6109                                                    (size_t)r->in._data_size);
6110         if (buffer_written == (ssize_t)-1) {
6111                 *r->out.num_written = 0;
6112                 if (errno == ENOSPC)
6113                         return WERR_NO_SPOOL_SPACE;
6114                 else
6115                         return WERR_ACCESS_DENIED;
6116         }
6117
6118         *r->out.num_written = r->in._data_size;
6119
6120         return WERR_OK;
6121 }
6122
6123 /********************************************************************
6124  * api_spoolss_getprinter
6125  * called from the spoolss dispatcher
6126  *
6127  ********************************************************************/
6128
6129 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6130                               struct pipes_struct *p)
6131 {
6132         struct dcesrv_call_state *dce_call = p->dce_call;
6133         struct auth_session_info *session_info =
6134                 dcesrv_call_session_info(dce_call);
6135         int snum;
6136         WERROR errcode = WERR_INVALID_FUNCTION;
6137         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6138
6139         if (!Printer) {
6140                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6141                         OUR_HANDLE(handle)));
6142                 return WERR_INVALID_HANDLE;
6143         }
6144
6145         if (!get_printer_snum(p, handle, &snum, NULL))
6146                 return WERR_INVALID_HANDLE;
6147
6148         switch (command) {
6149         case SPOOLSS_PRINTER_CONTROL_PAUSE:
6150                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6151                 break;
6152         case SPOOLSS_PRINTER_CONTROL_RESUME:
6153         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6154                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6155                 break;
6156         case SPOOLSS_PRINTER_CONTROL_PURGE:
6157                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6158                 break;
6159         default:
6160                 return WERR_INVALID_LEVEL;
6161         }
6162
6163         return errcode;
6164 }
6165
6166
6167 /****************************************************************
6168  _spoolss_AbortPrinter
6169  * From MSDN: "Deletes printer's spool file if printer is configured
6170  * for spooling"
6171 ****************************************************************/
6172
6173 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6174                              struct spoolss_AbortPrinter *r)
6175 {
6176         struct dcesrv_call_state *dce_call = p->dce_call;
6177         struct auth_session_info *session_info =
6178                 dcesrv_call_session_info(dce_call);
6179         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
6180         int             snum;
6181         WERROR          errcode = WERR_OK;
6182
6183         if (!Printer) {
6184                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6185                         OUR_HANDLE(r->in.handle)));
6186                 return WERR_INVALID_HANDLE;
6187         }
6188
6189         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6190                 return WERR_INVALID_HANDLE;
6191
6192         if (!Printer->document_started) {
6193                 return WERR_SPL_NO_STARTDOC;
6194         }
6195
6196         errcode = print_job_delete(session_info,
6197                                    p->msg_ctx,
6198                                    snum,
6199                                    Printer->jobid);
6200
6201         return errcode;
6202 }
6203
6204 /********************************************************************
6205  * called by spoolss_api_setprinter
6206  * when updating a printer description
6207  ********************************************************************/
6208
6209 static WERROR update_printer_sec(struct policy_handle *handle,
6210                                  struct pipes_struct *p,
6211                                  struct sec_desc_buf *secdesc_ctr)
6212 {
6213         struct spoolss_security_descriptor *new_secdesc = NULL;
6214         struct spoolss_security_descriptor *old_secdesc = NULL;
6215         const char *printer = NULL;
6216         WERROR result;
6217         int snum = -1;
6218         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6219         struct dcerpc_binding_handle *b;
6220         TALLOC_CTX *tmp_ctx = NULL;
6221         bool ok = false;
6222
6223         if (!Printer) {
6224                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6225                          OUR_HANDLE(handle)));
6226
6227                 result = WERR_INVALID_HANDLE;
6228                 goto done;
6229         }
6230
6231         if (secdesc_ctr == NULL) {
6232                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6233                 result = WERR_INVALID_PARAMETER;
6234                 goto done;
6235         }
6236
6237         switch (Printer->printer_type) {
6238         case SPLHND_SERVER:
6239                 break;
6240         case SPLHND_PRINTER:
6241                 if (!get_printer_snum(p, handle, &snum, NULL)) {
6242                         DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6243                                  OUR_HANDLE(handle)));
6244                         result = WERR_INVALID_HANDLE;
6245                         goto done;
6246                 }
6247                 printer = lp_const_servicename(snum);
6248                 break;
6249         default:
6250                 break;
6251         }
6252
6253         /* Check the user has permissions to change the security
6254            descriptor.  By experimentation with two NT machines, the user
6255            requires Full Access to the printer to change security
6256            information. */
6257
6258         switch (Printer->printer_type) {
6259         case SPLHND_SERVER:
6260                 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6261                 break;
6262         case SPLHND_PRINTER:
6263                 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6264                 break;
6265         default:
6266                 break;
6267         }
6268
6269         if (!ok) {
6270                 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6271                         "(access_granted: 0x%08x)\n", Printer->access_granted));
6272                 result = WERR_ACCESS_DENIED;
6273                 goto done;
6274         }
6275
6276         tmp_ctx = talloc_new(p->mem_ctx);
6277         if (!tmp_ctx) {
6278                 return WERR_NOT_ENOUGH_MEMORY;
6279         }
6280
6281         result = winreg_printer_binding_handle(tmp_ctx,
6282                                                get_session_info_system(),
6283                                                p->msg_ctx,
6284                                                &b);
6285         if (!W_ERROR_IS_OK(result)) {
6286                 goto done;
6287         }
6288
6289         /* NT seems to like setting the security descriptor even though
6290            nothing may have actually changed. */
6291
6292         if (printer != NULL) {
6293                 result = winreg_get_printer_secdesc(tmp_ctx, b,
6294                                                     printer,
6295                                                     &old_secdesc);
6296         } else {
6297                 result = winreg_get_printserver_secdesc(tmp_ctx, b,
6298                                                         &old_secdesc);
6299         }
6300         if (!W_ERROR_IS_OK(result)) {
6301                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6302                 result = WERR_INVALID_HANDLE;
6303                 goto done;
6304         }
6305
6306         if (DEBUGLEVEL >= 10) {
6307                 struct dom_sid_buf buf;
6308                 struct security_acl *the_acl;
6309                 int i;
6310
6311                 the_acl = old_secdesc->dacl;
6312                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6313                            printer, the_acl->num_aces));
6314
6315                 for (i = 0; i < the_acl->num_aces; i++) {
6316                         DEBUG(10, ("%s 0x%08x\n",
6317                                    dom_sid_str_buf(
6318                                            &the_acl->aces[i].trustee,
6319                                            &buf),
6320                                   the_acl->aces[i].access_mask));
6321                 }
6322
6323                 the_acl = secdesc_ctr->sd->dacl;
6324
6325                 if (the_acl) {
6326                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6327                                    printer, the_acl->num_aces));
6328
6329                         for (i = 0; i < the_acl->num_aces; i++) {
6330                                 DEBUG(10, ("%s 0x%08x\n",
6331                                            dom_sid_str_buf(
6332                                                    &the_acl->aces[i].trustee,
6333                                                    &buf),
6334                                            the_acl->aces[i].access_mask));
6335                         }
6336                 } else {
6337                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6338                 }
6339         }
6340
6341         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6342         if (new_secdesc == NULL) {
6343                 result = WERR_NOT_ENOUGH_MEMORY;
6344                 goto done;
6345         }
6346
6347         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6348                 result = WERR_OK;
6349                 goto done;
6350         }
6351
6352         if (printer != NULL) {
6353                 result = winreg_set_printer_secdesc(tmp_ctx, b,
6354                                                     printer,
6355                                                     new_secdesc);
6356         } else {
6357                 result = winreg_set_printserver_secdesc(tmp_ctx, b,
6358                                                         new_secdesc);
6359         }
6360
6361 done:
6362         talloc_free(tmp_ctx);
6363         return result;
6364 }
6365
6366 /********************************************************************
6367  Canonicalize printer info from a client
6368  ********************************************************************/
6369
6370 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6371                              struct spoolss_SetPrinterInfo2 *info2,
6372                              int snum)
6373 {
6374         fstring printername;
6375         const char *p;
6376
6377         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6378                 "portname=%s drivername=%s comment=%s location=%s\n",
6379                 info2->servername, info2->printername, info2->sharename,
6380                 info2->portname, info2->drivername, info2->comment,
6381                 info2->location));
6382
6383         /* we force some elements to "correct" values */
6384         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6385         if (info2->servername == NULL) {
6386                 return false;
6387         }
6388         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6389         if (info2->sharename == NULL) {
6390                 return false;
6391         }
6392
6393         /* check to see if we allow printername != sharename */
6394         if (lp_force_printername(snum)) {
6395                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6396                                         lp_netbios_name(), info2->sharename);
6397         } else {
6398                 /* make sure printername is in \\server\printername format */
6399                 fstrcpy(printername, info2->printername);
6400                 p = printername;
6401                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6402                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6403                                 p++;
6404                 }
6405
6406                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6407                                         lp_netbios_name(), p);
6408         }
6409         if (info2->printername == NULL) {
6410                 return false;
6411         }
6412
6413         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6414         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6415
6416         return true;
6417 }
6418
6419 /****************************************************************************
6420 ****************************************************************************/
6421
6422 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6423 {
6424         const struct loadparm_substitution *lp_sub =
6425                 loadparm_s3_global_substitution();
6426         char *cmd = lp_addport_command(talloc_tos(), lp_sub);
6427         char *command = NULL;
6428         int ret;
6429         bool is_print_op = false;
6430
6431         if ( !*cmd ) {
6432                 return WERR_ACCESS_DENIED;
6433         }
6434
6435         command = talloc_asprintf(ctx,
6436                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6437         if (!command) {
6438                 return WERR_NOT_ENOUGH_MEMORY;
6439         }
6440
6441         if ( token )
6442                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6443
6444         DEBUG(10,("Running [%s]\n", command));
6445
6446         /********* BEGIN SePrintOperatorPrivilege **********/
6447
6448         if ( is_print_op )
6449                 become_root();
6450
6451         ret = smbrun(command, NULL, NULL);
6452
6453         if ( is_print_op )
6454                 unbecome_root();
6455
6456         /********* END SePrintOperatorPrivilege **********/
6457
6458         DEBUGADD(10,("returned [%d]\n", ret));
6459
6460         TALLOC_FREE(command);
6461
6462         if ( ret != 0 ) {
6463                 return WERR_ACCESS_DENIED;
6464         }
6465
6466         return WERR_OK;
6467 }
6468
6469 /****************************************************************************
6470 ****************************************************************************/
6471
6472 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6473                                    int snum)
6474 {
6475         /*
6476          * As we do not know if we are embedded in the file server process
6477          * or not, we have to pretend that all shares are in use.
6478          */
6479         return true;
6480 }
6481
6482 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6483                              struct spoolss_SetPrinterInfo2 *info2,
6484                              const char *remote_machine,
6485                              struct messaging_context *msg_ctx)
6486 {
6487         const struct loadparm_substitution *lp_sub =
6488                 loadparm_s3_global_substitution();
6489         char *cmd = lp_addprinter_command(talloc_tos(), lp_sub);
6490         char **qlines;
6491         char *command = NULL;
6492         int numlines;
6493         int ret;
6494         int fd;
6495         bool is_print_op = false;
6496
6497         if (!remote_machine) {
6498                 return false;
6499         }
6500
6501         command = talloc_asprintf(ctx,
6502                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6503                         cmd, info2->printername, info2->sharename,
6504                         info2->portname, info2->drivername,
6505                         info2->location, info2->comment, remote_machine);
6506         if (!command) {
6507                 return false;
6508         }
6509
6510         if ( token )
6511                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6512
6513         DEBUG(10,("Running [%s]\n", command));
6514
6515         /********* BEGIN SePrintOperatorPrivilege **********/
6516
6517         if ( is_print_op )
6518                 become_root();
6519
6520         ret = smbrun(command, &fd, NULL);
6521         if (ret == 0) {
6522                 /* Tell everyone we updated smb.conf. */
6523                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
6524         }
6525
6526         if ( is_print_op )
6527                 unbecome_root();
6528
6529         /********* END SePrintOperatorPrivilege **********/
6530
6531         DEBUGADD(10,("returned [%d]\n", ret));
6532
6533         TALLOC_FREE(command);
6534
6535         if ( ret != 0 ) {
6536                 if (fd != -1)
6537                         close(fd);
6538                 return false;
6539         }
6540
6541         /* reload our services immediately */
6542         become_root();
6543         reload_services(NULL, spoolss_conn_snum_used, false);
6544         unbecome_root();
6545
6546         numlines = 0;
6547         /* Get lines and convert them back to dos-codepage */
6548         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6549         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6550         close(fd);
6551
6552         /* Set the portname to what the script says the portname should be. */
6553         /* but don't require anything to be return from the script exit a good error code */
6554
6555         if (numlines) {
6556                 /* Set the portname to what the script says the portname should be. */
6557                 info2->portname = talloc_strdup(ctx, qlines[0]);
6558                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6559         }
6560
6561         TALLOC_FREE(qlines);
6562         return true;
6563 }
6564
6565 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6566                                const struct auth_session_info *session_info,
6567                                struct messaging_context *msg_ctx,
6568                                int snum,
6569                                struct spoolss_SetPrinterInfo2 *printer,
6570                                struct spoolss_PrinterInfo2 *old_printer)
6571 {
6572         bool force_update = (old_printer == NULL);
6573         const char *dnsdomname;
6574         const char *longname;
6575         const char *uncname;
6576         const char *spooling;
6577         DATA_BLOB buffer;
6578         WERROR result = WERR_OK;
6579         struct dcerpc_binding_handle *b;
6580         TALLOC_CTX *tmp_ctx;
6581         bool ok;
6582
6583         tmp_ctx = talloc_new(mem_ctx);
6584         if (!tmp_ctx) {
6585                 return WERR_NOT_ENOUGH_MEMORY;
6586         }
6587
6588         result = winreg_printer_binding_handle(tmp_ctx,
6589                                                session_info,
6590                                                msg_ctx,
6591                                                &b);
6592         if (!W_ERROR_IS_OK(result)) {
6593                 goto done;
6594         }
6595
6596         if (printer->drivername != NULL &&
6597             (force_update ||
6598              !strequal(printer->drivername, old_printer->drivername))) {
6599                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6600                 if (!ok) {
6601                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6602                         result = WERR_INVALID_DATA;
6603                         goto done;
6604                 }
6605                 result = winreg_set_printer_dataex(tmp_ctx, b,
6606                                           printer->sharename,
6607                                           SPOOL_DSSPOOLER_KEY,
6608                                           SPOOL_REG_DRIVERNAME,
6609                                           REG_SZ,
6610                                           buffer.data,
6611                                           buffer.length);
6612                 if (!W_ERROR_IS_OK(result)) {
6613                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6614                         goto done;
6615                 }
6616
6617                 if (!force_update) {
6618                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6619                                 printer->drivername));
6620
6621                         notify_printer_driver(global_event_context(), msg_ctx,
6622                                               snum, printer->drivername ?
6623                                               printer->drivername : "");
6624                 }
6625         }
6626
6627         if (printer->comment != NULL &&
6628             (force_update ||
6629              !strequal(printer->comment, old_printer->comment))) {
6630                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6631                 if (!ok) {
6632                         DEBUG(0, ("comment data corrupted\n"));
6633                         result = WERR_INVALID_DATA;
6634                         goto done;
6635                 }
6636                 result = winreg_set_printer_dataex(tmp_ctx, b,
6637                                           printer->sharename,
6638                                           SPOOL_DSSPOOLER_KEY,
6639                                           SPOOL_REG_DESCRIPTION,
6640                                           REG_SZ,
6641                                           buffer.data,
6642                                           buffer.length);
6643                 if (!W_ERROR_IS_OK(result)) {
6644                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6645                         goto done;
6646                 }
6647
6648                 if (!force_update) {
6649                         notify_printer_comment(global_event_context(), msg_ctx,
6650                                                snum, printer->comment ?
6651                                                printer->comment : "");
6652                 }
6653         }
6654
6655         if (printer->sharename != NULL &&
6656             (force_update ||
6657              !strequal(printer->sharename, old_printer->sharename))) {
6658                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6659                 if (!ok) {
6660                         DEBUG(0, ("sharename data corrupted\n"));
6661                         result = WERR_INVALID_DATA;
6662                         goto done;
6663                 }
6664                 result = winreg_set_printer_dataex(tmp_ctx, b,
6665                                           printer->sharename,
6666                                           SPOOL_DSSPOOLER_KEY,
6667                                           SPOOL_REG_PRINTSHARENAME,
6668                                           REG_SZ,
6669                                           buffer.data,
6670                                           buffer.length);
6671                 if (!W_ERROR_IS_OK(result)) {
6672                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6673                         goto done;
6674                 }
6675
6676                 if (!force_update) {
6677                         notify_printer_sharename(global_event_context(),
6678                                                  msg_ctx,
6679                                                  snum, printer->sharename ?
6680                                                  printer->sharename : "");
6681                 }
6682
6683                 /* name change, purge any cache entries for the old */
6684                 prune_printername_cache();
6685         }
6686
6687         if (printer->printername != NULL &&
6688             (force_update ||
6689              !strequal(printer->printername, old_printer->printername))) {
6690                 const char *p;
6691
6692                 p = strrchr(printer->printername, '\\' );
6693                 if (p != NULL) {
6694                         p++;
6695                 } else {
6696                         p = printer->printername;
6697                 }
6698
6699                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6700                 if (!ok) {
6701                         DEBUG(0, ("printername data corrupted\n"));
6702                         result = WERR_INVALID_DATA;
6703                         goto done;
6704                 }
6705                 result = winreg_set_printer_dataex(tmp_ctx, b,
6706                                           printer->sharename,
6707                                           SPOOL_DSSPOOLER_KEY,
6708                                           SPOOL_REG_PRINTERNAME,
6709                                           REG_SZ,
6710                                           buffer.data,
6711                                           buffer.length);
6712                 if (!W_ERROR_IS_OK(result)) {
6713                         DBG_ERR("Failed to set %s\n", SPOOL_REG_PRINTERNAME);
6714                         goto done;
6715                 }
6716
6717                 if (!force_update) {
6718                         notify_printer_printername(global_event_context(),
6719                                                    msg_ctx, snum, p ? p : "");
6720                 }
6721
6722                 /* name change, purge any cache entries for the old */
6723                 prune_printername_cache();
6724         }
6725
6726         if (printer->portname != NULL &&
6727             (force_update ||
6728              !strequal(printer->portname, old_printer->portname))) {
6729                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6730                 if (!ok) {
6731                         DEBUG(0, ("portname data corrupted\n"));
6732                         result = WERR_INVALID_DATA;
6733                         goto done;
6734                 }
6735                 result = winreg_set_printer_dataex(tmp_ctx, b,
6736                                           printer->sharename,
6737                                           SPOOL_DSSPOOLER_KEY,
6738                                           SPOOL_REG_PORTNAME,
6739                                           REG_SZ,
6740                                           buffer.data,
6741                                           buffer.length);
6742                 if (!W_ERROR_IS_OK(result)) {
6743                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6744                         goto done;
6745                 }
6746
6747                 if (!force_update) {
6748                         notify_printer_port(global_event_context(),
6749                                             msg_ctx, snum, printer->portname ?
6750                                             printer->portname : "");
6751                 }
6752         }
6753
6754         if (printer->location != NULL &&
6755             (force_update ||
6756              !strequal(printer->location, old_printer->location))) {
6757                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6758                 if (!ok) {
6759                         DEBUG(0, ("location data corrupted\n"));
6760                         result = WERR_INVALID_DATA;
6761                         goto done;
6762                 }
6763                 result = winreg_set_printer_dataex(tmp_ctx, b,
6764                                           printer->sharename,
6765                                           SPOOL_DSSPOOLER_KEY,
6766                                           SPOOL_REG_LOCATION,
6767                                           REG_SZ,
6768                                           buffer.data,
6769                                           buffer.length);
6770                 if (!W_ERROR_IS_OK(result)) {
6771                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6772                         goto done;
6773                 }
6774
6775                 if (!force_update) {
6776                         notify_printer_location(global_event_context(),
6777                                                 msg_ctx, snum,
6778                                                 printer->location ?
6779                                                 printer->location : "");
6780                 }
6781         }
6782
6783         if (printer->sepfile != NULL &&
6784             (force_update ||
6785              !strequal(printer->sepfile, old_printer->sepfile))) {
6786                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6787                 if (!ok) {
6788                         DEBUG(0, ("sepfile data corrupted\n"));
6789                         result = WERR_INVALID_DATA;
6790                         goto done;
6791                 }
6792                 result = winreg_set_printer_dataex(tmp_ctx, b,
6793                                           printer->sharename,
6794                                           SPOOL_DSSPOOLER_KEY,
6795                                           SPOOL_REG_PRINTSEPARATORFILE,
6796                                           REG_SZ,
6797                                           buffer.data,
6798                                           buffer.length);
6799                 if (!W_ERROR_IS_OK(result)) {
6800                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6801                         goto done;
6802                 }
6803
6804                 if (!force_update) {
6805                         notify_printer_sepfile(global_event_context(),
6806                                                msg_ctx, snum,
6807                                                printer->sepfile ?
6808                                                printer->sepfile : "");
6809                 }
6810         }
6811
6812         if (printer->starttime != 0 &&
6813             (force_update ||
6814              printer->starttime != old_printer->starttime)) {
6815                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6816                 SIVAL(buffer.data, 0, printer->starttime);
6817                 result = winreg_set_printer_dataex(tmp_ctx, b,
6818                                           printer->sharename,
6819                                           SPOOL_DSSPOOLER_KEY,
6820                                           SPOOL_REG_PRINTSTARTTIME,
6821                                           REG_DWORD,
6822                                           buffer.data,
6823                                           buffer.length);
6824                 if (!W_ERROR_IS_OK(result)) {
6825                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6826                         goto done;
6827                 }
6828         }
6829
6830         if (printer->untiltime != 0 &&
6831             (force_update ||
6832              printer->untiltime != old_printer->untiltime)) {
6833                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6834                 SIVAL(buffer.data, 0, printer->untiltime);
6835                 result = winreg_set_printer_dataex(tmp_ctx, b,
6836                                           printer->sharename,
6837                                           SPOOL_DSSPOOLER_KEY,
6838                                           SPOOL_REG_PRINTENDTIME,
6839                                           REG_DWORD,
6840                                           buffer.data,
6841                                           buffer.length);
6842                 if (!W_ERROR_IS_OK(result)) {
6843                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6844                         goto done;
6845                 }
6846         }
6847
6848         if (force_update || printer->priority != old_printer->priority) {
6849                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6850                 SIVAL(buffer.data, 0, printer->priority);
6851                 result = winreg_set_printer_dataex(tmp_ctx, b,
6852                                           printer->sharename,
6853                                           SPOOL_DSSPOOLER_KEY,
6854                                           SPOOL_REG_PRIORITY,
6855                                           REG_DWORD,
6856                                           buffer.data,
6857                                           buffer.length);
6858                 if (!W_ERROR_IS_OK(result)) {
6859                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6860                         goto done;
6861                 }
6862         }
6863
6864         if (force_update || printer->attributes != old_printer->attributes) {
6865                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6866                 SIVAL(buffer.data, 0, (printer->attributes &
6867                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6868                 result = winreg_set_printer_dataex(tmp_ctx, b,
6869                                           printer->sharename,
6870                                           SPOOL_DSSPOOLER_KEY,
6871                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6872                                           REG_DWORD,
6873                                           buffer.data,
6874                                           buffer.length);
6875                 if (!W_ERROR_IS_OK(result)) {
6876                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6877                         goto done;
6878                 }
6879
6880                 switch (printer->attributes & 0x3) {
6881                         case 0:
6882                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6883                                 break;
6884                         case 1:
6885                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6886                                 break;
6887                         case 2:
6888                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6889                                 break;
6890                         default:
6891                                 spooling = "unknown";
6892                 }
6893                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6894                 if (!ok) {
6895                         DEBUG(0, ("printSpooling data corrupted\n"));
6896                         result = WERR_INVALID_DATA;
6897                         goto done;
6898                 }
6899                 winreg_set_printer_dataex(tmp_ctx, b,
6900                                           printer->sharename,
6901                                           SPOOL_DSSPOOLER_KEY,
6902                                           SPOOL_REG_PRINTSPOOLING,
6903                                           REG_SZ,
6904                                           buffer.data,
6905                                           buffer.length);
6906         }
6907
6908         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6909         if (!ok) {
6910                 DEBUG(0, ("shortServerName data corrupted\n"));
6911                 result = WERR_INVALID_DATA;
6912                 goto done;
6913         }
6914         result = winreg_set_printer_dataex(tmp_ctx, b,
6915                                   printer->sharename,
6916                                   SPOOL_DSSPOOLER_KEY,
6917                                   SPOOL_REG_SHORTSERVERNAME,
6918                                   REG_SZ,
6919                                   buffer.data,
6920                                   buffer.length);
6921         if (!W_ERROR_IS_OK(result)) {
6922                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6923                 goto done;
6924         }
6925
6926         dnsdomname = get_mydnsfullname();
6927         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6928                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6929         } else {
6930                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6931         }
6932         if (longname == NULL) {
6933                 result = WERR_NOT_ENOUGH_MEMORY;
6934                 goto done;
6935         }
6936
6937         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6938         if (!ok) {
6939                 DEBUG(0, ("longname data corrupted\n"));
6940                 result = WERR_INVALID_DATA;
6941                 goto done;
6942         }
6943         result = winreg_set_printer_dataex(tmp_ctx, b,
6944                                            printer->sharename,
6945                                            SPOOL_DSSPOOLER_KEY,
6946                                            SPOOL_REG_SERVERNAME,
6947                                            REG_SZ,
6948                                            buffer.data,
6949                                            buffer.length);
6950         if (!W_ERROR_IS_OK(result)) {
6951                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6952                 goto done;
6953         }
6954
6955         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6956                                   lp_netbios_name(), printer->sharename);
6957         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6958         if (!ok) {
6959                 DEBUG(0, ("uncName data corrupted\n"));
6960                 result = WERR_INVALID_DATA;
6961                 goto done;
6962         }
6963         result = winreg_set_printer_dataex(tmp_ctx, b,
6964                                   printer->sharename,
6965                                   SPOOL_DSSPOOLER_KEY,
6966                                   SPOOL_REG_UNCNAME,
6967                                   REG_SZ,
6968                                   buffer.data,
6969                                   buffer.length);
6970         if (!W_ERROR_IS_OK(result)) {
6971                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6972                 goto done;
6973         }
6974
6975 done:
6976         talloc_free(tmp_ctx);
6977         return result;
6978 }
6979
6980 /********************************************************************
6981  * Called by spoolss_api_setprinter
6982  * when updating a printer description.
6983  ********************************************************************/
6984
6985 static WERROR update_printer(struct pipes_struct *p,
6986                              struct policy_handle *handle,
6987                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6988                              struct spoolss_DeviceMode *devmode)
6989 {
6990         struct dcesrv_call_state *dce_call = p->dce_call;
6991         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
6992         const struct tsocket_address *remote_address =
6993                 dcesrv_connection_get_remote_address(dcesrv_conn);
6994         struct auth_session_info *session_info =
6995                 dcesrv_call_session_info(dce_call);
6996         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6997         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6998         struct spoolss_PrinterInfo2 *old_printer;
6999         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7000         const struct loadparm_substitution *lp_sub =
7001                 loadparm_s3_global_substitution();
7002         int snum;
7003         WERROR result = WERR_OK;
7004         TALLOC_CTX *tmp_ctx;
7005         struct dcerpc_binding_handle *b;
7006
7007         DEBUG(8,("update_printer\n"));
7008
7009         tmp_ctx = talloc_new(p->mem_ctx);
7010         if (tmp_ctx == NULL) {
7011                 return WERR_NOT_ENOUGH_MEMORY;
7012         }
7013
7014         if (!Printer) {
7015                 result = WERR_INVALID_HANDLE;
7016                 goto done;
7017         }
7018
7019         if (!get_printer_snum(p, handle, &snum, NULL)) {
7020                 result = WERR_INVALID_HANDLE;
7021                 goto done;
7022         }
7023
7024         result = winreg_printer_binding_handle(tmp_ctx,
7025                                                get_session_info_system(),
7026                                                p->msg_ctx,
7027                                                &b);
7028         if (!W_ERROR_IS_OK(result)) {
7029                 goto done;
7030         }
7031
7032         result = winreg_get_printer(tmp_ctx, b,
7033                                     lp_const_servicename(snum),
7034                                     &old_printer);
7035         if (!W_ERROR_IS_OK(result)) {
7036                 result = WERR_INVALID_HANDLE;
7037                 goto done;
7038         }
7039
7040         /* Do sanity check on the requested changes for Samba */
7041         if (!check_printer_ok(tmp_ctx, printer, snum)) {
7042                 result = WERR_INVALID_PARAMETER;
7043                 goto done;
7044         }
7045
7046         /* FIXME!!! If the driver has changed we really should verify that
7047            it is installed before doing much else   --jerry */
7048
7049         /* Check calling user has permission to update printer description */
7050         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7051                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7052                 result = WERR_ACCESS_DENIED;
7053                 goto done;
7054         }
7055
7056         /* Call addprinter hook */
7057         /* Check changes to see if this is really needed */
7058
7059         if (*lp_addprinter_command(talloc_tos(), lp_sub) &&
7060                         (!strequal(printer->drivername, old_printer->drivername) ||
7061                          !strequal(printer->comment, old_printer->comment) ||
7062                          !strequal(printer->portname, old_printer->portname) ||
7063                          !strequal(printer->location, old_printer->location)) )
7064         {
7065                 char *raddr;
7066
7067                 raddr = tsocket_address_inet_addr_string(remote_address,
7068                                                          p->mem_ctx);
7069                 if (raddr == NULL) {
7070                         result = WERR_NOT_ENOUGH_MEMORY;
7071                         goto done;
7072                 }
7073
7074                 /* add_printer_hook() will call reload_services() */
7075                 if (!add_printer_hook(tmp_ctx, session_info->security_token,
7076                                       printer, raddr,
7077                                       p->msg_ctx)) {
7078                         result = WERR_ACCESS_DENIED;
7079                         goto done;
7080                 }
7081         }
7082
7083         result = update_dsspooler(tmp_ctx,
7084                                   get_session_info_system(),
7085                                   p->msg_ctx,
7086                                   snum,
7087                                   printer,
7088                                   old_printer);
7089         if (!W_ERROR_IS_OK(result)) {
7090                 goto done;
7091         }
7092
7093         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
7094
7095         if (devmode == NULL) {
7096                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
7097         }
7098         result = winreg_update_printer(tmp_ctx, b,
7099                                        printer->sharename,
7100                                        printer_mask,
7101                                        printer,
7102                                        devmode,
7103                                        NULL);
7104
7105 done:
7106         talloc_free(tmp_ctx);
7107
7108         return result;
7109 }
7110
7111 /****************************************************************************
7112 ****************************************************************************/
7113 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
7114                                            struct policy_handle *handle,
7115                                            struct spoolss_SetPrinterInfo7 *info7)
7116 {
7117 #ifdef HAVE_ADS
7118         const struct loadparm_substitution *lp_sub =
7119                 loadparm_s3_global_substitution();
7120         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7121         WERROR result;
7122         int snum;
7123         struct printer_handle *Printer;
7124
7125         if ( lp_security() != SEC_ADS ) {
7126                 return WERR_INVALID_LEVEL;
7127         }
7128
7129         Printer = find_printer_index_by_hnd(p, handle);
7130
7131         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
7132
7133         if (!Printer)
7134                 return WERR_INVALID_HANDLE;
7135
7136         if (!get_printer_snum(p, handle, &snum, NULL))
7137                 return WERR_INVALID_HANDLE;
7138
7139         result = winreg_get_printer_internal(p->mem_ctx,
7140                                     get_session_info_system(),
7141                                     p->msg_ctx,
7142                                     lp_servicename(talloc_tos(), lp_sub, snum),
7143                                     &pinfo2);
7144         if (!W_ERROR_IS_OK(result)) {
7145                 return WERR_INVALID_HANDLE;
7146         }
7147
7148         nt_printer_publish(pinfo2,
7149                            get_session_info_system(),
7150                            p->msg_ctx,
7151                            pinfo2,
7152                            info7->action);
7153
7154         TALLOC_FREE(pinfo2);
7155         return WERR_OK;
7156 #else
7157         return WERR_INVALID_LEVEL;
7158 #endif
7159 }
7160
7161 /********************************************************************
7162  ********************************************************************/
7163
7164 static WERROR update_printer_devmode(struct pipes_struct *p,
7165                                      struct policy_handle *handle,
7166                                      struct spoolss_DeviceMode *devmode)
7167 {
7168         int snum;
7169         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7170         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7171
7172         DEBUG(8,("update_printer_devmode\n"));
7173
7174         if (!Printer) {
7175                 return WERR_INVALID_HANDLE;
7176         }
7177
7178         if (!get_printer_snum(p, handle, &snum, NULL)) {
7179                 return WERR_INVALID_HANDLE;
7180         }
7181
7182         /* Check calling user has permission to update printer description */
7183         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7184                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7185                 return WERR_ACCESS_DENIED;
7186         }
7187
7188         return winreg_update_printer_internal(p->mem_ctx,
7189                                      get_session_info_system(),
7190                                      p->msg_ctx,
7191                                      lp_const_servicename(snum),
7192                                      info2_mask,
7193                                      NULL,
7194                                      devmode,
7195                                      NULL);
7196 }
7197
7198
7199 /****************************************************************
7200  _spoolss_SetPrinter
7201 ****************************************************************/
7202
7203 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7204                            struct spoolss_SetPrinter *r)
7205 {
7206         WERROR result;
7207
7208         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7209
7210         if (!Printer) {
7211                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7212                         OUR_HANDLE(r->in.handle)));
7213                 return WERR_INVALID_HANDLE;
7214         }
7215
7216         /* check the level */
7217         switch (r->in.info_ctr->level) {
7218                 case 0:
7219                         return control_printer(r->in.handle, r->in.command, p);
7220                 case 2:
7221                         result = update_printer(p, r->in.handle,
7222                                                 r->in.info_ctr,
7223                                                 r->in.devmode_ctr->devmode);
7224                         if (!W_ERROR_IS_OK(result))
7225                                 return result;
7226                         if (r->in.secdesc_ctr->sd)
7227                                 result = update_printer_sec(r->in.handle, p,
7228                                                             r->in.secdesc_ctr);
7229                         return result;
7230                 case 3:
7231                         return update_printer_sec(r->in.handle, p,
7232                                                   r->in.secdesc_ctr);
7233                 case 4: {
7234                         struct spoolss_PrinterInfo2 *old_printer;
7235                         struct spoolss_SetPrinterInfo2 *set_old_printer;
7236                         struct spoolss_SetPrinterInfoCtr *info_ctr;
7237                         struct dcerpc_binding_handle *b;
7238                         int snum;
7239                         TALLOC_CTX *tmp_ctx;
7240
7241                         tmp_ctx = talloc_new(p->mem_ctx);
7242                         if (tmp_ctx == NULL) {
7243                                 return WERR_NOT_ENOUGH_MEMORY;
7244                         }
7245
7246                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7247                                 TALLOC_FREE(tmp_ctx);
7248                                 return WERR_INVALID_HANDLE;
7249                         }
7250
7251                         result = winreg_printer_binding_handle(tmp_ctx,
7252                                                                get_session_info_system(),
7253                                                                p->msg_ctx,
7254                                                                &b);
7255                         if (!W_ERROR_IS_OK(result)) {
7256                                 TALLOC_FREE(tmp_ctx);
7257                                 return result;
7258                         }
7259
7260                         result = winreg_get_printer(tmp_ctx, b,
7261                                                     lp_const_servicename(snum),
7262                                                     &old_printer);
7263                         if (!W_ERROR_IS_OK(result)) {
7264                                 TALLOC_FREE(tmp_ctx);
7265                                 return WERR_INVALID_HANDLE;
7266                         }
7267
7268                         old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7269                         if (old_printer->servername == NULL) {
7270                                 TALLOC_FREE(tmp_ctx);
7271                                 return WERR_NOT_ENOUGH_MEMORY;
7272                         }
7273
7274                         old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7275                         if (old_printer->printername == NULL) {
7276                                 TALLOC_FREE(tmp_ctx);
7277                                 return WERR_NOT_ENOUGH_MEMORY;
7278                         }
7279
7280                         old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7281
7282                         set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7283                         if (set_old_printer == NULL) {
7284                                 TALLOC_FREE(tmp_ctx);
7285                                 return WERR_NOT_ENOUGH_MEMORY;
7286                         }
7287
7288                         spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7289
7290                         info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7291                         if (info_ctr == NULL) {
7292                                 TALLOC_FREE(tmp_ctx);
7293                                 return WERR_NOT_ENOUGH_MEMORY;
7294                         }
7295
7296                         info_ctr->level = 2;
7297                         info_ctr->info.info2 = set_old_printer;
7298
7299                         result = update_printer(p, r->in.handle,
7300                                                 info_ctr,
7301                                                 r->in.devmode_ctr->devmode);
7302
7303                         if (!W_ERROR_IS_OK(result)) {
7304                                 TALLOC_FREE(tmp_ctx);
7305                                 return result;
7306                         }
7307
7308                         if (r->in.secdesc_ctr->sd) {
7309                                 result = update_printer_sec(r->in.handle, p,
7310                                                             r->in.secdesc_ctr);
7311                         }
7312
7313                         TALLOC_FREE(tmp_ctx);
7314                         return result;
7315                 }
7316                 case 7:
7317                         return publish_or_unpublish_printer(p, r->in.handle,
7318                                                             r->in.info_ctr->info.info7);
7319                 case 8:
7320                         return update_printer_devmode(p, r->in.handle,
7321                                                       r->in.devmode_ctr->devmode);
7322                 default:
7323                         return WERR_INVALID_LEVEL;
7324         }
7325 }
7326
7327 /****************************************************************
7328  _spoolss_FindClosePrinterNotify
7329 ****************************************************************/
7330
7331 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7332                                        struct spoolss_FindClosePrinterNotify *r)
7333 {
7334         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7335
7336         if (!Printer) {
7337                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7338                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7339                 return WERR_INVALID_HANDLE;
7340         }
7341
7342         if (Printer->notify.cli_chan != NULL &&
7343             Printer->notify.cli_chan->active_connections > 0) {
7344                 int snum = -1;
7345
7346                 if (Printer->printer_type == SPLHND_PRINTER) {
7347                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7348                                 return WERR_INVALID_HANDLE;
7349                         }
7350                 }
7351
7352                 srv_spoolss_replycloseprinter(snum, Printer);
7353         }
7354
7355         Printer->notify.flags=0;
7356         Printer->notify.options=0;
7357         Printer->notify.localmachine[0]='\0';
7358         Printer->notify.printerlocal=0;
7359         TALLOC_FREE(Printer->notify.option);
7360
7361         return WERR_OK;
7362 }
7363
7364 /****************************************************************
7365  _spoolss_AddJob
7366 ****************************************************************/
7367
7368 WERROR _spoolss_AddJob(struct pipes_struct *p,
7369                        struct spoolss_AddJob *r)
7370 {
7371         if (!r->in.buffer && (r->in.offered != 0)) {
7372                 return WERR_INVALID_PARAMETER;
7373         }
7374
7375         /* this is what a NT server returns for AddJob. AddJob must fail on
7376          * non-local printers */
7377
7378         if (r->in.level != 1) {
7379                 return WERR_INVALID_LEVEL;
7380         }
7381
7382         return WERR_INVALID_PARAMETER;
7383 }
7384
7385 /****************************************************************************
7386 fill_job_info1
7387 ****************************************************************************/
7388
7389 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7390                              struct spoolss_JobInfo1 *r,
7391                              const print_queue_struct *queue,
7392                              uint32_t jobid,
7393                              int position, int snum,
7394                              struct spoolss_PrinterInfo2 *pinfo2)
7395 {
7396         const struct loadparm_substitution *lp_sub =
7397                 loadparm_s3_global_substitution();
7398         struct tm *t;
7399
7400         t = gmtime(&queue->time);
7401
7402         r->job_id               = jobid;
7403
7404         r->printer_name         = lp_servicename(mem_ctx, lp_sub, snum);
7405         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7406         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7407         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7408         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7409         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7410         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7411         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7412         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7413         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7414         r->text_status          = talloc_strdup(mem_ctx, "");
7415         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7416
7417         r->status               = nt_printj_status(queue->status);
7418         r->priority             = queue->priority;
7419         r->position             = position;
7420         r->total_pages          = queue->page_count;
7421         r->pages_printed        = 0; /* ??? */
7422
7423         init_systemtime(&r->submitted, t);
7424
7425         return WERR_OK;
7426 }
7427
7428 /****************************************************************************
7429 fill_job_info2
7430 ****************************************************************************/
7431
7432 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7433                              struct spoolss_JobInfo2 *r,
7434                              const print_queue_struct *queue,
7435                              uint32_t jobid,
7436                              int position, int snum,
7437                              struct spoolss_PrinterInfo2 *pinfo2,
7438                              struct spoolss_DeviceMode *devmode)
7439 {
7440         const struct loadparm_substitution *lp_sub =
7441                 loadparm_s3_global_substitution();
7442         struct tm *t;
7443
7444         t = gmtime(&queue->time);
7445
7446         r->job_id               = jobid;
7447
7448         r->printer_name         = lp_servicename(mem_ctx, lp_sub, snum);
7449         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7450         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7451         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7452         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7453         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7454         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7455         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7456         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7457         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7458         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7459         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7460         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7461         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7462         r->parameters           = talloc_strdup(mem_ctx, "");
7463         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7464         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7465         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7466
7467         r->devmode              = devmode;
7468
7469         r->text_status          = talloc_strdup(mem_ctx, "");
7470         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7471
7472         r->secdesc              = NULL;
7473
7474         r->status               = nt_printj_status(queue->status);
7475         r->priority             = queue->priority;
7476         r->position             = position;
7477         r->start_time           = 0;
7478         r->until_time           = 0;
7479         r->total_pages          = queue->page_count;
7480         r->size                 = queue->size;
7481         init_systemtime(&r->submitted, t);
7482         r->time                 = 0;
7483         r->pages_printed        = 0; /* ??? */
7484
7485         return WERR_OK;
7486 }
7487
7488 /****************************************************************************
7489  Enumjobs at level 1.
7490 ****************************************************************************/
7491
7492 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7493                               const print_queue_struct *queue,
7494                               uint32_t num_queues, int snum,
7495                               struct spoolss_PrinterInfo2 *pinfo2,
7496                               union spoolss_JobInfo **info_p,
7497                               uint32_t *count)
7498 {
7499         union spoolss_JobInfo *info;
7500         int i;
7501         WERROR result = WERR_OK;
7502         uint32_t num_filled;
7503         struct tdb_print_db *pdb;
7504
7505         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7506         if (info == NULL) {
7507                 result = WERR_NOT_ENOUGH_MEMORY;
7508                 goto err_out;
7509         }
7510
7511         pdb = get_print_db_byname(pinfo2->sharename);
7512         if (pdb == NULL) {
7513                 result = WERR_INVALID_PARAMETER;
7514                 goto err_info_free;
7515         }
7516
7517         num_filled = 0;
7518         for (i = 0; i < num_queues; i++) {
7519                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7520                 if (jobid == (uint32_t)-1) {
7521                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7522                         continue;
7523                 }
7524
7525                 result = fill_job_info1(info,
7526                                         &info[num_filled].info1,
7527                                         &queue[i],
7528                                         jobid,
7529                                         i,
7530                                         snum,
7531                                         pinfo2);
7532                 if (!W_ERROR_IS_OK(result)) {
7533                         goto err_pdb_drop;
7534                 }
7535
7536                 num_filled++;
7537         }
7538
7539         release_print_db(pdb);
7540         *info_p = info;
7541         *count = num_filled;
7542
7543         return WERR_OK;
7544
7545 err_pdb_drop:
7546         release_print_db(pdb);
7547 err_info_free:
7548         TALLOC_FREE(info);
7549 err_out:
7550         *count = 0;
7551         return result;
7552 }
7553
7554 /****************************************************************************
7555  Enumjobs at level 2.
7556 ****************************************************************************/
7557
7558 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7559                               const print_queue_struct *queue,
7560                               uint32_t num_queues, int snum,
7561                               struct spoolss_PrinterInfo2 *pinfo2,
7562                               union spoolss_JobInfo **info_p,
7563                               uint32_t *count)
7564 {
7565         union spoolss_JobInfo *info;
7566         int i;
7567         WERROR result = WERR_OK;
7568         uint32_t num_filled;
7569         struct tdb_print_db *pdb;
7570
7571         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7572         if (info == NULL) {
7573                 result = WERR_NOT_ENOUGH_MEMORY;
7574                 goto err_out;
7575         }
7576
7577         pdb = get_print_db_byname(pinfo2->sharename);
7578         if (pdb == NULL) {
7579                 result = WERR_INVALID_PARAMETER;
7580                 goto err_info_free;
7581         }
7582
7583         num_filled = 0;
7584         for (i = 0; i< num_queues; i++) {
7585                 struct spoolss_DeviceMode *devmode;
7586                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7587                 if (jobid == (uint32_t)-1) {
7588                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7589                         continue;
7590                 }
7591
7592                 result = spoolss_create_default_devmode(info,
7593                                                         pinfo2->printername,
7594                                                         &devmode);
7595                 if (!W_ERROR_IS_OK(result)) {
7596                         DEBUG(3, ("Can't proceed w/o a devmode!\n"));
7597                         goto err_pdb_drop;
7598                 }
7599
7600                 result = fill_job_info2(info,
7601                                         &info[num_filled].info2,
7602                                         &queue[i],
7603                                         jobid,
7604                                         i,
7605                                         snum,
7606                                         pinfo2,
7607                                         devmode);
7608                 if (!W_ERROR_IS_OK(result)) {
7609                         goto err_pdb_drop;
7610                 }
7611                 num_filled++;
7612         }
7613
7614         release_print_db(pdb);
7615         *info_p = info;
7616         *count = num_filled;
7617
7618         return WERR_OK;
7619
7620 err_pdb_drop:
7621         release_print_db(pdb);
7622 err_info_free:
7623         TALLOC_FREE(info);
7624 err_out:
7625         *count = 0;
7626         return result;
7627 }
7628
7629 /****************************************************************************
7630  Enumjobs at level 3.
7631 ****************************************************************************/
7632
7633 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7634                               const print_queue_struct *queue,
7635                               uint32_t num_queues, int snum,
7636                               struct spoolss_PrinterInfo2 *pinfo2,
7637                               union spoolss_JobInfo **info_p,
7638                               uint32_t *count)
7639 {
7640         union spoolss_JobInfo *info;
7641         int i;
7642         WERROR result = WERR_OK;
7643         uint32_t num_filled;
7644         struct tdb_print_db *pdb;
7645
7646         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7647         if (info == NULL) {
7648                 result = WERR_NOT_ENOUGH_MEMORY;
7649                 goto err_out;
7650         }
7651
7652         pdb = get_print_db_byname(pinfo2->sharename);
7653         if (pdb == NULL) {
7654                 result = WERR_INVALID_PARAMETER;
7655                 goto err_info_free;
7656         }
7657
7658         num_filled = 0;
7659         for (i = 0; i < num_queues; i++) {
7660                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7661                 if (jobid == (uint32_t)-1) {
7662                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7663                         continue;
7664                 }
7665
7666                 info[num_filled].info3.job_id = jobid;
7667                 /* next_job_id is overwritten on next iteration */
7668                 info[num_filled].info3.next_job_id = 0;
7669                 info[num_filled].info3.reserved = 0;
7670
7671                 if (num_filled > 0) {
7672                         info[num_filled - 1].info3.next_job_id = jobid;
7673                 }
7674                 num_filled++;
7675         }
7676
7677         release_print_db(pdb);
7678         *info_p = info;
7679         *count = num_filled;
7680
7681         return WERR_OK;
7682
7683 err_info_free:
7684         TALLOC_FREE(info);
7685 err_out:
7686         *count = 0;
7687         return result;
7688 }
7689
7690 /****************************************************************
7691  _spoolss_EnumJobs
7692 ****************************************************************/
7693
7694 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7695                          struct spoolss_EnumJobs *r)
7696 {
7697         WERROR result;
7698         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7699         int snum;
7700         print_status_struct prt_status;
7701         print_queue_struct *queue = NULL;
7702         uint32_t count;
7703
7704         /* that's an [in out] buffer */
7705
7706         if (!r->in.buffer && (r->in.offered != 0)) {
7707                 return WERR_INVALID_PARAMETER;
7708         }
7709
7710         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7711                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7712                 return WERR_INVALID_LEVEL;
7713         }
7714
7715         DEBUG(4,("_spoolss_EnumJobs\n"));
7716
7717         *r->out.needed = 0;
7718         *r->out.count = 0;
7719         *r->out.info = NULL;
7720
7721         /* lookup the printer snum and tdb entry */
7722
7723         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7724                 return WERR_INVALID_HANDLE;
7725         }
7726
7727         result = winreg_get_printer_internal(p->mem_ctx,
7728                                     get_session_info_system(),
7729                                     p->msg_ctx,
7730                                     lp_const_servicename(snum),
7731                                     &pinfo2);
7732         if (!W_ERROR_IS_OK(result)) {
7733                 return result;
7734         }
7735
7736         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7737         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7738                 count, prt_status.status, prt_status.message));
7739
7740         if (count == 0) {
7741                 SAFE_FREE(queue);
7742                 TALLOC_FREE(pinfo2);
7743                 return WERR_OK;
7744         }
7745
7746         switch (r->in.level) {
7747         case 1:
7748                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7749                                          pinfo2, r->out.info, r->out.count);
7750                 break;
7751         case 2:
7752                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7753                                          pinfo2, r->out.info, r->out.count);
7754                 break;
7755         case 3:
7756                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7757                                          pinfo2, r->out.info, r->out.count);
7758                 break;
7759         default:
7760                 SMB_ASSERT(false);      /* level checked on entry */
7761                 break;
7762         }
7763
7764         SAFE_FREE(queue);
7765         TALLOC_FREE(pinfo2);
7766
7767         if (!W_ERROR_IS_OK(result)) {
7768                 return result;
7769         }
7770
7771         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7772                                                      spoolss_EnumJobs,
7773                                                      *r->out.info, r->in.level,
7774                                                      *r->out.count);
7775         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7776         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7777
7778         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7779 }
7780
7781 /****************************************************************
7782  _spoolss_ScheduleJob
7783 ****************************************************************/
7784
7785 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7786                             struct spoolss_ScheduleJob *r)
7787 {
7788         return WERR_OK;
7789 }
7790
7791 /****************************************************************
7792 ****************************************************************/
7793
7794 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7795                                struct messaging_context *msg_ctx,
7796                                const char *printer_name,
7797                                uint32_t job_id,
7798                                struct spoolss_SetJobInfo1 *r)
7799 {
7800         char *old_doc_name;
7801
7802         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7803                 return WERR_INVALID_HANDLE;
7804         }
7805
7806         if (strequal(old_doc_name, r->document_name)) {
7807                 return WERR_OK;
7808         }
7809
7810         if (!print_job_set_name(global_event_context(), msg_ctx,
7811                                 printer_name, job_id, r->document_name)) {
7812                 return WERR_INVALID_HANDLE;
7813         }
7814
7815         return WERR_OK;
7816 }
7817
7818 /****************************************************************
7819  _spoolss_SetJob
7820 ****************************************************************/
7821
7822 WERROR _spoolss_SetJob(struct pipes_struct *p,
7823                        struct spoolss_SetJob *r)
7824 {
7825         struct dcesrv_call_state *dce_call = p->dce_call;
7826         struct auth_session_info *session_info =
7827                 dcesrv_call_session_info(dce_call);
7828         int snum;
7829         WERROR errcode = WERR_INVALID_FUNCTION;
7830
7831         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7832                 return WERR_INVALID_HANDLE;
7833         }
7834
7835         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7836                 return WERR_INVALID_PRINTER_NAME;
7837         }
7838
7839         switch (r->in.command) {
7840         case SPOOLSS_JOB_CONTROL_CANCEL:
7841         case SPOOLSS_JOB_CONTROL_DELETE:
7842                 errcode = print_job_delete(session_info, p->msg_ctx,
7843                                            snum, r->in.job_id);
7844                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7845                         errcode = WERR_OK;
7846                 }
7847                 break;
7848         case SPOOLSS_JOB_CONTROL_PAUSE:
7849                 errcode = print_job_pause(session_info, p->msg_ctx,
7850                                           snum, r->in.job_id);
7851                 break;
7852         case SPOOLSS_JOB_CONTROL_RESTART:
7853         case SPOOLSS_JOB_CONTROL_RESUME:
7854                 errcode = print_job_resume(session_info, p->msg_ctx,
7855                                            snum, r->in.job_id);
7856                 break;
7857         case SPOOLSS_JOB_CONTROL_NOOP:
7858                 errcode = WERR_OK;
7859                 break;
7860         default:
7861                 return WERR_INVALID_LEVEL;
7862         }
7863
7864         if (!W_ERROR_IS_OK(errcode)) {
7865                 return errcode;
7866         }
7867
7868         if (r->in.ctr == NULL) {
7869                 return errcode;
7870         }
7871
7872         switch (r->in.ctr->level) {
7873         case 1:
7874                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7875                                            lp_const_servicename(snum),
7876                                            r->in.job_id,
7877                                            r->in.ctr->info.info1);
7878                 break;
7879         case 2:
7880         case 3:
7881         case 4:
7882         default:
7883                 return WERR_INVALID_LEVEL;
7884         }
7885
7886         return errcode;
7887 }
7888
7889 /****************************************************************************
7890  Enumerates all printer drivers by level and architecture.
7891 ****************************************************************************/
7892
7893 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7894                                                        const struct auth_session_info *session_info,
7895                                                        struct messaging_context *msg_ctx,
7896                                                        const char *servername,
7897                                                        const char *architecture,
7898                                                        uint32_t level,
7899                                                        union spoolss_DriverInfo **info_p,
7900                                                        uint32_t *count_p)
7901 {
7902         int i;
7903         uint32_t version;
7904         struct spoolss_DriverInfo8 *driver;
7905         union spoolss_DriverInfo *info = NULL;
7906         uint32_t count = 0;
7907         WERROR result = WERR_OK;
7908         uint32_t num_drivers;
7909         const char **drivers;
7910         struct dcerpc_binding_handle *b;
7911         TALLOC_CTX *tmp_ctx = NULL;
7912
7913         *count_p = 0;
7914         *info_p = NULL;
7915
7916         tmp_ctx = talloc_new(mem_ctx);
7917         if (!tmp_ctx) {
7918                 return WERR_NOT_ENOUGH_MEMORY;
7919         }
7920
7921         result = winreg_printer_binding_handle(tmp_ctx,
7922                                                session_info,
7923                                                msg_ctx,
7924                                                &b);
7925         if (!W_ERROR_IS_OK(result)) {
7926                 goto out;
7927         }
7928
7929         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7930                 result = winreg_get_driver_list(tmp_ctx, b,
7931                                                 architecture, version,
7932                                                 &num_drivers, &drivers);
7933                 if (!W_ERROR_IS_OK(result)) {
7934                         goto out;
7935                 }
7936                 DEBUG(4, ("we have:[%d] drivers in environment"
7937                           " [%s] and version [%d]\n",
7938                           num_drivers, architecture, version));
7939
7940                 if (num_drivers != 0) {
7941                         info = talloc_realloc(tmp_ctx, info,
7942                                                     union spoolss_DriverInfo,
7943                                                     count + num_drivers);
7944                         if (!info) {
7945                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7946                                         "failed to enlarge driver info buffer!\n"));
7947                                 result = WERR_NOT_ENOUGH_MEMORY;
7948                                 goto out;
7949                         }
7950                 }
7951
7952                 for (i = 0; i < num_drivers; i++) {
7953                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7954
7955                         result = winreg_get_driver(tmp_ctx, b,
7956                                                    architecture, drivers[i],
7957                                                    version, &driver);
7958                         if (!W_ERROR_IS_OK(result)) {
7959                                 goto out;
7960                         }
7961
7962                         switch (level) {
7963                         case 1:
7964                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7965                                                                    driver, servername);
7966                                 break;
7967                         case 2:
7968                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7969                                                                    driver, servername);
7970                                 break;
7971                         case 3:
7972                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7973                                                                    driver, servername);
7974                                 break;
7975                         case 4:
7976                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7977                                                                    driver, servername);
7978                                 break;
7979                         case 5:
7980                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7981                                                                    driver, servername);
7982                                 break;
7983                         case 6:
7984                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7985                                                                    driver, servername);
7986                                 break;
7987                         case 8:
7988                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7989                                                                    driver, servername);
7990                                 break;
7991                         default:
7992                                 result = WERR_INVALID_LEVEL;
7993                                 break;
7994                         }
7995
7996                         TALLOC_FREE(driver);
7997
7998                         if (!W_ERROR_IS_OK(result)) {
7999                                 goto out;
8000                         }
8001                 }
8002
8003                 count += num_drivers;
8004                 TALLOC_FREE(drivers);
8005         }
8006
8007 out:
8008         if (W_ERROR_IS_OK(result)) {
8009                 *info_p = talloc_move(mem_ctx, &info);
8010                 *count_p = count;
8011         }
8012
8013         talloc_free(tmp_ctx);
8014         return result;
8015 }
8016
8017 /****************************************************************************
8018  Enumerates all printer drivers by level.
8019 ****************************************************************************/
8020
8021 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
8022                                        const struct auth_session_info *session_info,
8023                                        struct messaging_context *msg_ctx,
8024                                        const char *servername,
8025                                        const char *architecture,
8026                                        uint32_t level,
8027                                        union spoolss_DriverInfo **info_p,
8028                                        uint32_t *count_p)
8029 {
8030         uint32_t a,i;
8031         WERROR result = WERR_OK;
8032
8033         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
8034
8035                 for (a=0; archi_table[a].long_archi != NULL; a++) {
8036
8037                         union spoolss_DriverInfo *info = NULL;
8038                         uint32_t count = 0;
8039
8040                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
8041                                                                           session_info,
8042                                                                           msg_ctx,
8043                                                                           servername,
8044                                                                           archi_table[a].long_archi,
8045                                                                           level,
8046                                                                           &info,
8047                                                                           &count);
8048                         if (!W_ERROR_IS_OK(result)) {
8049                                 continue;
8050                         }
8051
8052                         for (i=0; i < count; i++) {
8053                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
8054                                              info[i], info_p, count_p);
8055                         }
8056                 }
8057
8058                 return result;
8059         }
8060
8061         return enumprinterdrivers_level_by_architecture(mem_ctx,
8062                                                         session_info,
8063                                                         msg_ctx,
8064                                                         servername,
8065                                                         architecture,
8066                                                         level,
8067                                                         info_p,
8068                                                         count_p);
8069 }
8070
8071 /****************************************************************
8072  _spoolss_EnumPrinterDrivers
8073 ****************************************************************/
8074
8075 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
8076                                    struct spoolss_EnumPrinterDrivers *r)
8077 {
8078         const char *cservername;
8079         WERROR result;
8080
8081         /* that's an [in out] buffer */
8082
8083         if (!r->in.buffer && (r->in.offered != 0)) {
8084                 return WERR_INVALID_PARAMETER;
8085         }
8086
8087         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
8088
8089         *r->out.needed = 0;
8090         *r->out.count = 0;
8091         *r->out.info = NULL;
8092
8093         cservername = canon_servername(r->in.server);
8094
8095         if (!is_myname_or_ipaddr(cservername)) {
8096                 return WERR_UNKNOWN_PRINTER_DRIVER;
8097         }
8098
8099         result = enumprinterdrivers_level(p->mem_ctx,
8100                                           get_session_info_system(),
8101                                           p->msg_ctx,
8102                                           cservername,
8103                                           r->in.environment,
8104                                           r->in.level,
8105                                           r->out.info,
8106                                           r->out.count);
8107         if (!W_ERROR_IS_OK(result)) {
8108                 return result;
8109         }
8110
8111         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8112                                                      spoolss_EnumPrinterDrivers,
8113                                                      *r->out.info, r->in.level,
8114                                                      *r->out.count);
8115         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8116         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8117
8118         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8119 }
8120
8121 /****************************************************************
8122  _spoolss_EnumForms
8123 ****************************************************************/
8124
8125 WERROR _spoolss_EnumForms(struct pipes_struct *p,
8126                           struct spoolss_EnumForms *r)
8127 {
8128         WERROR result;
8129
8130         *r->out.count = 0;
8131         *r->out.needed = 0;
8132         *r->out.info = NULL;
8133
8134         /* that's an [in out] buffer */
8135
8136         if (!r->in.buffer && (r->in.offered != 0) ) {
8137                 return WERR_INVALID_PARAMETER;
8138         }
8139
8140         DEBUG(4,("_spoolss_EnumForms\n"));
8141         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8142         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
8143
8144         switch (r->in.level) {
8145         case 1:
8146                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
8147                                                    get_session_info_system(),
8148                                                    p->msg_ctx,
8149                                                    r->out.count,
8150                                                    r->out.info);
8151                 break;
8152         default:
8153                 result = WERR_INVALID_LEVEL;
8154                 break;
8155         }
8156
8157         if (!W_ERROR_IS_OK(result)) {
8158                 return result;
8159         }
8160
8161         if (*r->out.count == 0) {
8162                 return WERR_NO_MORE_ITEMS;
8163         }
8164
8165         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8166                                                      spoolss_EnumForms,
8167                                                      *r->out.info, r->in.level,
8168                                                      *r->out.count);
8169         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8170         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8171
8172         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8173 }
8174
8175 /****************************************************************
8176  _spoolss_GetForm
8177 ****************************************************************/
8178
8179 WERROR _spoolss_GetForm(struct pipes_struct *p,
8180                         struct spoolss_GetForm *r)
8181 {
8182         WERROR result;
8183
8184         /* that's an [in out] buffer */
8185
8186         if (!r->in.buffer && (r->in.offered != 0)) {
8187                 TALLOC_FREE(r->out.info);
8188                 return WERR_INVALID_PARAMETER;
8189         }
8190
8191         DEBUG(4,("_spoolss_GetForm\n"));
8192         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8193         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
8194
8195         switch (r->in.level) {
8196         case 1:
8197                 result = winreg_printer_getform1_internal(p->mem_ctx,
8198                                                  get_session_info_system(),
8199                                                  p->msg_ctx,
8200                                                  r->in.form_name,
8201                                                  &r->out.info->info1);
8202                 break;
8203         default:
8204                 result = WERR_INVALID_LEVEL;
8205                 break;
8206         }
8207
8208         if (!W_ERROR_IS_OK(result)) {
8209                 TALLOC_FREE(r->out.info);
8210                 return result;
8211         }
8212
8213         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8214                                                r->out.info, r->in.level);
8215         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8216
8217         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8218 }
8219
8220 /****************************************************************************
8221 ****************************************************************************/
8222
8223 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8224                           struct spoolss_PortInfo1 *r,
8225                           const char *name)
8226 {
8227         r->port_name = talloc_strdup(mem_ctx, name);
8228         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8229
8230         return WERR_OK;
8231 }
8232
8233 /****************************************************************************
8234  TODO: This probably needs distinguish between TCP/IP and Local ports
8235  somehow.
8236 ****************************************************************************/
8237
8238 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8239                           struct spoolss_PortInfo2 *r,
8240                           const char *name)
8241 {
8242         r->port_name = talloc_strdup(mem_ctx, name);
8243         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8244
8245         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8246         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8247
8248         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8249         W_ERROR_HAVE_NO_MEMORY(r->description);
8250
8251         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8252         r->reserved = 0;
8253
8254         return WERR_OK;
8255 }
8256
8257
8258 /****************************************************************************
8259  wrapper around the enum ports command
8260 ****************************************************************************/
8261
8262 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8263 {
8264         const struct loadparm_substitution *lp_sub =
8265                 loadparm_s3_global_substitution();
8266         char *cmd = lp_enumports_command(talloc_tos(), lp_sub);
8267         char **qlines = NULL;
8268         char *command = NULL;
8269         int numlines;
8270         int ret;
8271         int fd;
8272
8273         *count = 0;
8274         *lines = NULL;
8275
8276         /* if no hook then just fill in the default port */
8277
8278         if ( !*cmd ) {
8279                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8280                         return WERR_NOT_ENOUGH_MEMORY;
8281                 }
8282                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8283                         TALLOC_FREE(qlines);
8284                         return WERR_NOT_ENOUGH_MEMORY;
8285                 }
8286                 qlines[1] = NULL;
8287                 numlines = 1;
8288         }
8289         else {
8290                 /* we have a valid enumport command */
8291
8292                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8293                 if (!command) {
8294                         return WERR_NOT_ENOUGH_MEMORY;
8295                 }
8296
8297                 DEBUG(10,("Running [%s]\n", command));
8298                 ret = smbrun(command, &fd, NULL);
8299                 DEBUG(10,("Returned [%d]\n", ret));
8300                 TALLOC_FREE(command);
8301                 if (ret != 0) {
8302                         if (fd != -1) {
8303                                 close(fd);
8304                         }
8305                         return WERR_ACCESS_DENIED;
8306                 }
8307
8308                 numlines = 0;
8309                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
8310                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8311                 close(fd);
8312         }
8313
8314         *count = numlines;
8315         *lines = qlines;
8316
8317         return WERR_OK;
8318 }
8319
8320 /****************************************************************************
8321  enumports level 1.
8322 ****************************************************************************/
8323
8324 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8325                                 union spoolss_PortInfo **info_p,
8326                                 uint32_t *count)
8327 {
8328         union spoolss_PortInfo *info = NULL;
8329         int i=0;
8330         WERROR result = WERR_OK;
8331         char **qlines = NULL;
8332         int numlines = 0;
8333
8334         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8335         if (!W_ERROR_IS_OK(result)) {
8336                 goto out;
8337         }
8338
8339         if (numlines) {
8340                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8341                 if (!info) {
8342                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8343                         result = WERR_NOT_ENOUGH_MEMORY;
8344                         goto out;
8345                 }
8346
8347                 for (i=0; i<numlines; i++) {
8348                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8349                         result = fill_port_1(info, &info[i].info1, qlines[i]);
8350                         if (!W_ERROR_IS_OK(result)) {
8351                                 goto out;
8352                         }
8353                 }
8354         }
8355         TALLOC_FREE(qlines);
8356
8357 out:
8358         if (!W_ERROR_IS_OK(result)) {
8359                 TALLOC_FREE(info);
8360                 TALLOC_FREE(qlines);
8361                 *count = 0;
8362                 *info_p = NULL;
8363                 return result;
8364         }
8365
8366         *info_p = info;
8367         *count = numlines;
8368
8369         return WERR_OK;
8370 }
8371
8372 /****************************************************************************
8373  enumports level 2.
8374 ****************************************************************************/
8375
8376 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8377                                 union spoolss_PortInfo **info_p,
8378                                 uint32_t *count)
8379 {
8380         union spoolss_PortInfo *info = NULL;
8381         int i=0;
8382         WERROR result = WERR_OK;
8383         char **qlines = NULL;
8384         int numlines = 0;
8385
8386         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8387         if (!W_ERROR_IS_OK(result)) {
8388                 goto out;
8389         }
8390
8391         if (numlines) {
8392                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8393                 if (!info) {
8394                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8395                         result = WERR_NOT_ENOUGH_MEMORY;
8396                         goto out;
8397                 }
8398
8399                 for (i=0; i<numlines; i++) {
8400                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8401                         result = fill_port_2(info, &info[i].info2, qlines[i]);
8402                         if (!W_ERROR_IS_OK(result)) {
8403                                 goto out;
8404                         }
8405                 }
8406         }
8407         TALLOC_FREE(qlines);
8408
8409 out:
8410         if (!W_ERROR_IS_OK(result)) {
8411                 TALLOC_FREE(info);
8412                 TALLOC_FREE(qlines);
8413                 *count = 0;
8414                 *info_p = NULL;
8415                 return result;
8416         }
8417
8418         *info_p = info;
8419         *count = numlines;
8420
8421         return WERR_OK;
8422 }
8423
8424 /****************************************************************
8425  _spoolss_EnumPorts
8426 ****************************************************************/
8427
8428 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8429                           struct spoolss_EnumPorts *r)
8430 {
8431         WERROR result;
8432
8433         /* that's an [in out] buffer */
8434
8435         if (!r->in.buffer && (r->in.offered != 0)) {
8436                 return WERR_INVALID_PARAMETER;
8437         }
8438
8439         DEBUG(4,("_spoolss_EnumPorts\n"));
8440
8441         *r->out.count = 0;
8442         *r->out.needed = 0;
8443         *r->out.info = NULL;
8444
8445         switch (r->in.level) {
8446         case 1:
8447                 result = enumports_level_1(p->mem_ctx, r->out.info,
8448                                            r->out.count);
8449                 break;
8450         case 2:
8451                 result = enumports_level_2(p->mem_ctx, r->out.info,
8452                                            r->out.count);
8453                 break;
8454         default:
8455                 return WERR_INVALID_LEVEL;
8456         }
8457
8458         if (!W_ERROR_IS_OK(result)) {
8459                 return result;
8460         }
8461
8462         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8463                                                      spoolss_EnumPorts,
8464                                                      *r->out.info, r->in.level,
8465                                                      *r->out.count);
8466         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8467         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8468
8469         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8470 }
8471
8472 /****************************************************************************
8473 ****************************************************************************/
8474
8475 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8476                                            const char *server,
8477                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8478                                            struct spoolss_DeviceMode *devmode,
8479                                            struct security_descriptor *secdesc,
8480                                            struct spoolss_UserLevelCtr *user_ctr,
8481                                            struct policy_handle *handle)
8482 {
8483         struct dcesrv_call_state *dce_call = p->dce_call;
8484         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
8485         const struct tsocket_address *remote_address =
8486                 dcesrv_connection_get_remote_address(dcesrv_conn);
8487         struct auth_session_info *session_info =
8488                 dcesrv_call_session_info(dce_call);
8489         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8490         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8491         const struct loadparm_substitution *lp_sub =
8492                 loadparm_s3_global_substitution();
8493         int     snum;
8494         WERROR err = WERR_OK;
8495
8496         /* samba does not have a concept of local, non-shared printers yet, so
8497          * make sure we always setup sharename - gd */
8498         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8499             (info2->printername != NULL && info2->printername[0] != '\0')) {
8500                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8501                         "no sharename has been set, setting printername %s as sharename\n",
8502                         info2->printername));
8503                 info2->sharename = info2->printername;
8504         }
8505
8506         /* check to see if the printer already exists */
8507         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8508                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8509                         info2->sharename));
8510                 return WERR_PRINTER_ALREADY_EXISTS;
8511         }
8512
8513         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8514                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8515                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8516                                 info2->printername));
8517                         return WERR_PRINTER_ALREADY_EXISTS;
8518                 }
8519         }
8520
8521         /* validate printer info struct */
8522         if (!info2->printername || strlen(info2->printername) == 0) {
8523                 return WERR_INVALID_PRINTER_NAME;
8524         }
8525         if (!info2->portname || strlen(info2->portname) == 0) {
8526                 return WERR_UNKNOWN_PORT;
8527         }
8528         if (!info2->drivername || strlen(info2->drivername) == 0) {
8529                 return WERR_UNKNOWN_PRINTER_DRIVER;
8530         }
8531         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8532                 return WERR_UNKNOWN_PRINTPROCESSOR;
8533         }
8534
8535         /* FIXME!!!  smbd should check to see if the driver is installed before
8536            trying to add a printer like this  --jerry */
8537
8538         if (*lp_addprinter_command(talloc_tos(), lp_sub) ) {
8539                 char *raddr;
8540
8541                 raddr = tsocket_address_inet_addr_string(remote_address,
8542                                                          p->mem_ctx);
8543                 if (raddr == NULL) {
8544                         return WERR_NOT_ENOUGH_MEMORY;
8545                 }
8546
8547                 if ( !add_printer_hook(p->mem_ctx, session_info->security_token,
8548                                        info2, raddr,
8549                                        p->msg_ctx) ) {
8550                         return WERR_ACCESS_DENIED;
8551                 }
8552         } else {
8553                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8554                         "smb.conf parameter \"addprinter command\" is defined. This "
8555                         "parameter must exist for this call to succeed\n",
8556                         info2->sharename ));
8557         }
8558
8559         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8560                 return WERR_ACCESS_DENIED;
8561         }
8562
8563         /* you must be a printer admin to add a new printer */
8564         if (!W_ERROR_IS_OK(print_access_check(session_info,
8565                                               p->msg_ctx,
8566                                               snum,
8567                                               PRINTER_ACCESS_ADMINISTER))) {
8568                 return WERR_ACCESS_DENIED;
8569         }
8570
8571         /*
8572          * Do sanity check on the requested changes for Samba.
8573          */
8574
8575         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8576                 return WERR_INVALID_PARAMETER;
8577         }
8578
8579         if (devmode == NULL) {
8580                 info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
8581         }
8582
8583         err = update_dsspooler(p->mem_ctx,
8584                                get_session_info_system(),
8585                                p->msg_ctx,
8586                                0,
8587                                info2,
8588                                NULL);
8589         if (!W_ERROR_IS_OK(err)) {
8590                 return err;
8591         }
8592
8593         err = winreg_update_printer_internal(p->mem_ctx,
8594                                     get_session_info_system(),
8595                                     p->msg_ctx,
8596                                     info2->sharename,
8597                                     info2_mask,
8598                                     info2,
8599                                     devmode,
8600                                     secdesc);
8601         if (!W_ERROR_IS_OK(err)) {
8602                 return err;
8603         }
8604
8605         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8606         if (!W_ERROR_IS_OK(err)) {
8607                 /* Handle open failed - remove addition. */
8608                 ZERO_STRUCTP(handle);
8609                 return err;
8610         }
8611
8612         return WERR_OK;
8613 }
8614
8615 /****************************************************************
8616  _spoolss_AddPrinterEx
8617 ****************************************************************/
8618
8619 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8620                              struct spoolss_AddPrinterEx *r)
8621 {
8622         switch (r->in.info_ctr->level) {
8623         case 1:
8624                 /* we don't handle yet */
8625                 /* but I know what to do ... */
8626                 return WERR_INVALID_LEVEL;
8627         case 2:
8628                 return spoolss_addprinterex_level_2(p, r->in.server,
8629                                                     r->in.info_ctr,
8630                                                     r->in.devmode_ctr->devmode,
8631                                                     r->in.secdesc_ctr->sd,
8632                                                     r->in.userlevel_ctr,
8633                                                     r->out.handle);
8634         default:
8635                 return WERR_INVALID_LEVEL;
8636         }
8637 }
8638
8639 /****************************************************************
8640  _spoolss_AddPrinter
8641 ****************************************************************/
8642
8643 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8644                            struct spoolss_AddPrinter *r)
8645 {
8646         struct spoolss_AddPrinterEx a;
8647         struct spoolss_UserLevelCtr userlevel_ctr;
8648
8649         ZERO_STRUCT(userlevel_ctr);
8650
8651         userlevel_ctr.level = 1;
8652
8653         a.in.server             = r->in.server;
8654         a.in.info_ctr           = r->in.info_ctr;
8655         a.in.devmode_ctr        = r->in.devmode_ctr;
8656         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8657         a.in.userlevel_ctr      = &userlevel_ctr;
8658         a.out.handle            = r->out.handle;
8659
8660         return _spoolss_AddPrinterEx(p, &a);
8661 }
8662
8663 /****************************************************************
8664  _spoolss_AddPrinterDriverEx
8665 ****************************************************************/
8666
8667 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8668                                    struct spoolss_AddPrinterDriverEx *r)
8669 {
8670         struct dcesrv_call_state *dce_call = p->dce_call;
8671         struct auth_session_info *session_info =
8672                 dcesrv_call_session_info(dce_call);
8673         WERROR err = WERR_OK;
8674         const char *driver_name = NULL;
8675         const char *driver_directory = NULL;
8676         uint32_t version;
8677
8678         /*
8679          * we only support the semantics of AddPrinterDriver()
8680          * i.e. only copy files that are newer than existing ones
8681          */
8682
8683         if (r->in.flags == 0) {
8684                 return WERR_INVALID_PARAMETER;
8685         }
8686
8687         if (!(r->in.flags & APD_COPY_ALL_FILES) &&
8688             !(r->in.flags & APD_COPY_NEW_FILES)) {
8689                 return WERR_ACCESS_DENIED;
8690         }
8691
8692         /* FIXME */
8693         if (r->in.info_ctr->level != 3 &&
8694             r->in.info_ctr->level != 6 &&
8695             r->in.info_ctr->level != 8) {
8696                 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8697                         r->in.info_ctr->level));
8698                 return WERR_INVALID_LEVEL;
8699         }
8700
8701         DEBUG(5,("Cleaning driver's information\n"));
8702         err = clean_up_driver_struct(p->mem_ctx,
8703                                      session_info,
8704                                      r->in.info_ctr,
8705                                      r->in.flags,
8706                                      &driver_directory);
8707         if (!W_ERROR_IS_OK(err)) {
8708                 DBG_ERR("clean_up_driver_struct failed - %s\n",
8709                         win_errstr(err));
8710                 goto done;
8711         }
8712
8713         DEBUG(5,("Moving driver to final destination\n"));
8714         err = move_driver_to_download_area(session_info,
8715                                            r->in.info_ctr,
8716                                            driver_directory);
8717         if (!W_ERROR_IS_OK(err)) {
8718                 DBG_ERR("move_driver_to_download_area failed - %s\n",
8719                         win_errstr(err));
8720                 goto done;
8721         }
8722
8723         err = winreg_add_driver_internal(p->mem_ctx,
8724                                 get_session_info_system(),
8725                                 p->msg_ctx,
8726                                 r->in.info_ctr,
8727                                 &driver_name,
8728                                 &version);
8729         if (!W_ERROR_IS_OK(err)) {
8730                 DBG_ERR("winreg_add_driver_internal failed - %s\n",
8731                         win_errstr(err));
8732                 goto done;
8733         }
8734
8735         /*
8736          * I think this is where the DrvUpgradePrinter() hook would be
8737          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8738          * server.  Right now, we just need to send ourselves a message
8739          * to update each printer bound to this driver.   --jerry
8740          */
8741
8742         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8743                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8744                         __func__, driver_name));
8745         }
8746
8747 done:
8748         return err;
8749 }
8750
8751 /****************************************************************
8752  _spoolss_AddPrinterDriver
8753 ****************************************************************/
8754
8755 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8756                                  struct spoolss_AddPrinterDriver *r)
8757 {
8758         struct spoolss_AddPrinterDriverEx a;
8759
8760         switch (r->in.info_ctr->level) {
8761         case 2:
8762         case 3:
8763         case 4:
8764         case 5:
8765                 break;
8766         default:
8767                 return WERR_INVALID_LEVEL;
8768         }
8769
8770         a.in.servername         = r->in.servername;
8771         a.in.info_ctr           = r->in.info_ctr;
8772         a.in.flags              = APD_COPY_NEW_FILES;
8773
8774         return _spoolss_AddPrinterDriverEx(p, &a);
8775 }
8776
8777 /****************************************************************************
8778 ****************************************************************************/
8779
8780 struct _spoolss_paths {
8781         int type;
8782         const char *share;
8783         const char *dir;
8784 };
8785
8786 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8787
8788 static const struct _spoolss_paths spoolss_paths[]= {
8789         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8790         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8791 };
8792
8793 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8794                                           const char *servername,
8795                                           const char *environment,
8796                                           int component,
8797                                           char **path)
8798 {
8799         const char *pservername = NULL;
8800         const char *long_archi;
8801         const char *short_archi;
8802
8803         *path = NULL;
8804
8805         /* environment may be empty */
8806         if (environment && strlen(environment)) {
8807                 long_archi = environment;
8808         } else {
8809                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8810                                                   "spoolss", "architecture",
8811                                                   GLOBAL_SPOOLSS_ARCHITECTURE);
8812         }
8813
8814         /* servername may be empty */
8815         if (servername && strlen(servername)) {
8816                 pservername = canon_servername(servername);
8817
8818                 if (!is_myname_or_ipaddr(pservername)) {
8819                         return WERR_INVALID_PARAMETER;
8820                 }
8821         }
8822
8823         if (!(short_archi = get_short_archi(long_archi))) {
8824                 return WERR_INVALID_ENVIRONMENT;
8825         }
8826
8827         switch (component) {
8828         case SPOOLSS_PRTPROCS_PATH:
8829         case SPOOLSS_DRIVER_PATH:
8830                 if (pservername) {
8831                         *path = talloc_asprintf(mem_ctx,
8832                                         "\\\\%s\\%s\\%s",
8833                                         pservername,
8834                                         spoolss_paths[component].share,
8835                                         short_archi);
8836                 } else {
8837                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8838                                         SPOOLSS_DEFAULT_SERVER_PATH,
8839                                         spoolss_paths[component].dir,
8840                                         short_archi);
8841                 }
8842                 break;
8843         default:
8844                 return WERR_INVALID_PARAMETER;
8845         }
8846
8847         if (!*path) {
8848                 return WERR_NOT_ENOUGH_MEMORY;
8849         }
8850
8851         return WERR_OK;
8852 }
8853
8854 /****************************************************************************
8855 ****************************************************************************/
8856
8857 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8858                                           const char *servername,
8859                                           const char *environment,
8860                                           struct spoolss_DriverDirectoryInfo1 *r)
8861 {
8862         WERROR werr;
8863         char *path = NULL;
8864
8865         werr = compose_spoolss_server_path(mem_ctx,
8866                                            servername,
8867                                            environment,
8868                                            SPOOLSS_DRIVER_PATH,
8869                                            &path);
8870         if (!W_ERROR_IS_OK(werr)) {
8871                 return werr;
8872         }
8873
8874         DEBUG(4,("printer driver directory: [%s]\n", path));
8875
8876         r->directory_name = path;
8877
8878         return WERR_OK;
8879 }
8880
8881 /****************************************************************
8882  _spoolss_GetPrinterDriverDirectory
8883 ****************************************************************/
8884
8885 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8886                                           struct spoolss_GetPrinterDriverDirectory *r)
8887 {
8888         WERROR werror;
8889
8890         /* that's an [in out] buffer */
8891
8892         if (!r->in.buffer && (r->in.offered != 0)) {
8893                 TALLOC_FREE(r->out.info);
8894                 return WERR_INVALID_PARAMETER;
8895         }
8896
8897         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8898                 r->in.level));
8899
8900         *r->out.needed = 0;
8901
8902         /* r->in.level is ignored */
8903
8904         werror = getprinterdriverdir_level_1(p->mem_ctx,
8905                                              r->in.server,
8906                                              r->in.environment,
8907                                              &r->out.info->info1);
8908         if (!W_ERROR_IS_OK(werror)) {
8909                 TALLOC_FREE(r->out.info);
8910                 return werror;
8911         }
8912
8913         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8914                                                r->out.info, r->in.level);
8915         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8916
8917         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8918 }
8919
8920 /****************************************************************
8921  _spoolss_EnumPrinterData
8922 ****************************************************************/
8923
8924 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8925                                 struct spoolss_EnumPrinterData *r)
8926 {
8927         WERROR result;
8928         struct spoolss_EnumPrinterDataEx r2;
8929         uint32_t count;
8930         struct spoolss_PrinterEnumValues *info, *val = NULL;
8931         uint32_t needed;
8932
8933         r2.in.handle    = r->in.handle;
8934         r2.in.key_name  = "PrinterDriverData";
8935         r2.in.offered   = 0;
8936         r2.out.count    = &count;
8937         r2.out.info     = &info;
8938         r2.out.needed   = &needed;
8939
8940         result = _spoolss_EnumPrinterDataEx(p, &r2);
8941         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8942                 r2.in.offered = needed;
8943                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8944         }
8945         if (!W_ERROR_IS_OK(result)) {
8946                 return result;
8947         }
8948
8949         /*
8950          * The NT machine wants to know the biggest size of value and data
8951          *
8952          * cf: MSDN EnumPrinterData remark section
8953          */
8954
8955         if (!r->in.value_offered && !r->in.data_offered) {
8956                 uint32_t biggest_valuesize = 0;
8957                 uint32_t biggest_datasize = 0;
8958                 int i, name_length;
8959
8960                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8961
8962                 for (i=0; i<count; i++) {
8963
8964                         name_length = strlen(info[i].value_name);
8965                         if (strlen(info[i].value_name) > biggest_valuesize) {
8966                                 biggest_valuesize = name_length;
8967                         }
8968
8969                         if (info[i].data_length > biggest_datasize) {
8970                                 biggest_datasize = info[i].data_length;
8971                         }
8972
8973                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8974                                 biggest_datasize));
8975                 }
8976
8977                 /* the value is an UNICODE string but real_value_size is the length
8978                    in bytes including the trailing 0 */
8979
8980                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8981                 *r->out.data_needed  = biggest_datasize;
8982
8983                 DEBUG(6,("final values: [%d], [%d]\n",
8984                         *r->out.value_needed, *r->out.data_needed));
8985
8986                 return WERR_OK;
8987         }
8988
8989         if (r->in.enum_index < count) {
8990                 val = &info[r->in.enum_index];
8991         }
8992
8993         if (val == NULL) {
8994                 /* out_value should default to "" or else NT4 has
8995                    problems unmarshalling the response */
8996
8997                 if (r->in.value_offered) {
8998                         *r->out.value_needed = 1;
8999                         r->out.value_name = talloc_strdup(r, "");
9000                         if (!r->out.value_name) {
9001                                 return WERR_NOT_ENOUGH_MEMORY;
9002                         }
9003                 } else {
9004                         r->out.value_name = NULL;
9005                         *r->out.value_needed = 0;
9006                 }
9007
9008                 /* the data is counted in bytes */
9009
9010                 *r->out.data_needed = r->in.data_offered;
9011
9012                 result = WERR_NO_MORE_ITEMS;
9013         } else {
9014                 /*
9015                  * the value is:
9016                  * - counted in bytes in the request
9017                  * - counted in UNICODE chars in the max reply
9018                  * - counted in bytes in the real size
9019                  *
9020                  * take a pause *before* coding not *during* coding
9021                  */
9022
9023                 /* name */
9024                 if (r->in.value_offered) {
9025                         r->out.value_name = talloc_strdup(r, val->value_name);
9026                         if (!r->out.value_name) {
9027                                 return WERR_NOT_ENOUGH_MEMORY;
9028                         }
9029                         *r->out.value_needed = val->value_name_len;
9030                 } else {
9031                         r->out.value_name = NULL;
9032                         *r->out.value_needed = 0;
9033                 }
9034
9035                 /* type */
9036
9037                 *r->out.type = val->type;
9038
9039                 /* data - counted in bytes */
9040
9041                 /*
9042                  * See the section "Dynamically Typed Query Parameters"
9043                  * in MS-RPRN.
9044                  */
9045
9046                 if (r->out.data && val->data && val->data->data &&
9047                                 val->data_length && r->in.data_offered) {
9048                         memcpy(r->out.data, val->data->data,
9049                                 MIN(val->data_length,r->in.data_offered));
9050                 }
9051
9052                 *r->out.data_needed = val->data_length;
9053
9054                 result = WERR_OK;
9055         }
9056
9057         return result;
9058 }
9059
9060 /****************************************************************
9061  _spoolss_SetPrinterData
9062 ****************************************************************/
9063
9064 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
9065                                struct spoolss_SetPrinterData *r)
9066 {
9067         struct spoolss_SetPrinterDataEx r2;
9068
9069         r2.in.handle            = r->in.handle;
9070         r2.in.key_name          = "PrinterDriverData";
9071         r2.in.value_name        = r->in.value_name;
9072         r2.in.type              = r->in.type;
9073         r2.in.data              = r->in.data;
9074         r2.in.offered           = r->in.offered;
9075
9076         return _spoolss_SetPrinterDataEx(p, &r2);
9077 }
9078
9079 /****************************************************************
9080  _spoolss_ResetPrinter
9081 ****************************************************************/
9082
9083 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
9084                              struct spoolss_ResetPrinter *r)
9085 {
9086         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9087         int             snum;
9088
9089         DEBUG(5,("_spoolss_ResetPrinter\n"));
9090
9091         /*
9092          * All we do is to check to see if the handle and queue is valid.
9093          * This call really doesn't mean anything to us because we only
9094          * support RAW printing.   --jerry
9095          */
9096
9097         if (!Printer) {
9098                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
9099                         OUR_HANDLE(r->in.handle)));
9100                 return WERR_INVALID_HANDLE;
9101         }
9102
9103         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9104                 return WERR_INVALID_HANDLE;
9105
9106
9107         /* blindly return success */
9108         return WERR_OK;
9109 }
9110
9111 /****************************************************************
9112  _spoolss_DeletePrinterData
9113 ****************************************************************/
9114
9115 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
9116                                   struct spoolss_DeletePrinterData *r)
9117 {
9118         struct spoolss_DeletePrinterDataEx r2;
9119
9120         r2.in.handle            = r->in.handle;
9121         r2.in.key_name          = "PrinterDriverData";
9122         r2.in.value_name        = r->in.value_name;
9123
9124         return _spoolss_DeletePrinterDataEx(p, &r2);
9125 }
9126
9127 /****************************************************************
9128  _spoolss_AddForm
9129 ****************************************************************/
9130
9131 WERROR _spoolss_AddForm(struct pipes_struct *p,
9132                         struct spoolss_AddForm *r)
9133 {
9134         struct dcesrv_call_state *dce_call = p->dce_call;
9135         struct auth_session_info *session_info =
9136                 dcesrv_call_session_info(dce_call);
9137         struct spoolss_AddFormInfo1 *form;
9138         int snum = -1;
9139         WERROR status = WERR_OK;
9140         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9141         struct dcerpc_binding_handle *b;
9142         TALLOC_CTX *tmp_ctx = NULL;
9143
9144         DEBUG(5,("_spoolss_AddForm\n"));
9145
9146         if (!Printer) {
9147                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
9148                         OUR_HANDLE(r->in.handle)));
9149                 return WERR_INVALID_HANDLE;
9150         }
9151
9152         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9153            and not a printer admin, then fail */
9154
9155         if ((session_info->unix_token->uid != sec_initial_uid()) &&
9156             !security_token_has_privilege(session_info->security_token,
9157                                           SEC_PRIV_PRINT_OPERATOR)) {
9158                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
9159                 return WERR_ACCESS_DENIED;
9160         }
9161
9162         if (r->in.info_ctr->level != 1) {
9163                 return WERR_INVALID_LEVEL;
9164         }
9165
9166         form = r->in.info_ctr->info.info1;
9167         if (!form) {
9168                 return WERR_INVALID_PARAMETER;
9169         }
9170
9171         switch (form->flags) {
9172         case SPOOLSS_FORM_USER:
9173         case SPOOLSS_FORM_BUILTIN:
9174         case SPOOLSS_FORM_PRINTER:
9175                 break;
9176         default:
9177                 return WERR_INVALID_PARAMETER;
9178         }
9179
9180         tmp_ctx = talloc_new(p->mem_ctx);
9181         if (!tmp_ctx) {
9182                 return WERR_NOT_ENOUGH_MEMORY;
9183         }
9184
9185         status = winreg_printer_binding_handle(tmp_ctx,
9186                                                get_session_info_system(),
9187                                                p->msg_ctx,
9188                                                &b);
9189         if (!W_ERROR_IS_OK(status)) {
9190                 goto done;
9191         }
9192
9193         status = winreg_printer_addform1(tmp_ctx, b, form);
9194         if (!W_ERROR_IS_OK(status)) {
9195                 goto done;
9196         }
9197
9198         /*
9199          * ChangeID must always be set if this is a printer
9200          */
9201         if (Printer->printer_type == SPLHND_PRINTER) {
9202                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9203                         status = WERR_INVALID_HANDLE;
9204                         goto done;
9205                 }
9206
9207                 status = winreg_printer_update_changeid(tmp_ctx, b,
9208                                                         lp_const_servicename(snum));
9209         }
9210
9211 done:
9212         talloc_free(tmp_ctx);
9213         return status;
9214 }
9215
9216 /****************************************************************
9217  _spoolss_DeleteForm
9218 ****************************************************************/
9219
9220 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9221                            struct spoolss_DeleteForm *r)
9222 {
9223         struct dcesrv_call_state *dce_call = p->dce_call;
9224         struct auth_session_info *session_info =
9225                 dcesrv_call_session_info(dce_call);
9226         const char *form_name = r->in.form_name;
9227         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9228         int snum = -1;
9229         WERROR status = WERR_OK;
9230         struct dcerpc_binding_handle *b;
9231         TALLOC_CTX *tmp_ctx = NULL;
9232
9233         DEBUG(5,("_spoolss_DeleteForm\n"));
9234
9235         if (!Printer) {
9236                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9237                         OUR_HANDLE(r->in.handle)));
9238                 return WERR_INVALID_HANDLE;
9239         }
9240
9241         if ((session_info->unix_token->uid != sec_initial_uid()) &&
9242             !security_token_has_privilege(session_info->security_token,
9243                                           SEC_PRIV_PRINT_OPERATOR)) {
9244                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9245                 return WERR_ACCESS_DENIED;
9246         }
9247
9248         tmp_ctx = talloc_new(p->mem_ctx);
9249         if (!tmp_ctx) {
9250                 return WERR_NOT_ENOUGH_MEMORY;
9251         }
9252
9253         status = winreg_printer_binding_handle(tmp_ctx,
9254                                                get_session_info_system(),
9255                                                p->msg_ctx,
9256                                                &b);
9257         if (!W_ERROR_IS_OK(status)) {
9258                 goto done;
9259         }
9260
9261         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9262         if (!W_ERROR_IS_OK(status)) {
9263                 goto done;
9264         }
9265
9266         /*
9267          * ChangeID must always be set if this is a printer
9268          */
9269         if (Printer->printer_type == SPLHND_PRINTER) {
9270                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9271                         status = WERR_INVALID_HANDLE;
9272                         goto done;
9273                 }
9274
9275                 status = winreg_printer_update_changeid(tmp_ctx, b,
9276                                                         lp_const_servicename(snum));
9277         }
9278
9279 done:
9280         talloc_free(tmp_ctx);
9281         return status;
9282 }
9283
9284 /****************************************************************
9285  _spoolss_SetForm
9286 ****************************************************************/
9287
9288 WERROR _spoolss_SetForm(struct pipes_struct *p,
9289                         struct spoolss_SetForm *r)
9290 {
9291         struct dcesrv_call_state *dce_call = p->dce_call;
9292         struct auth_session_info *session_info =
9293                 dcesrv_call_session_info(dce_call);
9294         struct spoolss_AddFormInfo1 *form;
9295         const char *form_name = r->in.form_name;
9296         int snum = -1;
9297         WERROR status = WERR_OK;
9298         struct dcerpc_binding_handle *b;
9299         TALLOC_CTX *tmp_ctx = NULL;
9300
9301         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9302
9303         DEBUG(5,("_spoolss_SetForm\n"));
9304
9305         if (!Printer) {
9306                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9307                         OUR_HANDLE(r->in.handle)));
9308                 return WERR_INVALID_HANDLE;
9309         }
9310
9311         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9312            and not a printer admin, then fail */
9313
9314         if ((session_info->unix_token->uid != sec_initial_uid()) &&
9315              !security_token_has_privilege(session_info->security_token,
9316                                            SEC_PRIV_PRINT_OPERATOR)) {
9317                 DEBUG(2,("_spoolss_SetForm: denied by insufficient permissions.\n"));
9318                 return WERR_ACCESS_DENIED;
9319         }
9320
9321         if (r->in.info_ctr->level != 1) {
9322                 return WERR_INVALID_LEVEL;
9323         }
9324
9325         form = r->in.info_ctr->info.info1;
9326         if (!form) {
9327                 return WERR_INVALID_PARAMETER;
9328         }
9329
9330         tmp_ctx = talloc_new(p->mem_ctx);
9331         if (!tmp_ctx) {
9332                 return WERR_NOT_ENOUGH_MEMORY;
9333         }
9334
9335         status = winreg_printer_binding_handle(tmp_ctx,
9336                                                get_session_info_system(),
9337                                                p->msg_ctx,
9338                                                &b);
9339         if (!W_ERROR_IS_OK(status)) {
9340                 goto done;
9341         }
9342
9343         status = winreg_printer_setform1(tmp_ctx, b,
9344                                          form_name,
9345                                          form);
9346         if (!W_ERROR_IS_OK(status)) {
9347                 goto done;
9348         }
9349
9350         /*
9351          * ChangeID must always be set if this is a printer
9352          */
9353         if (Printer->printer_type == SPLHND_PRINTER) {
9354                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9355                         status = WERR_INVALID_HANDLE;
9356                         goto done;
9357                 }
9358
9359                 status = winreg_printer_update_changeid(tmp_ctx, b,
9360                                                         lp_const_servicename(snum));
9361         }
9362
9363 done:
9364         talloc_free(tmp_ctx);
9365         return status;
9366 }
9367
9368 /****************************************************************************
9369  fill_print_processor1
9370 ****************************************************************************/
9371
9372 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9373                                     struct spoolss_PrintProcessorInfo1 *r,
9374                                     const char *print_processor_name)
9375 {
9376         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9377         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9378
9379         return WERR_OK;
9380 }
9381
9382 /****************************************************************************
9383  enumprintprocessors level 1.
9384 ****************************************************************************/
9385
9386 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9387                                           union spoolss_PrintProcessorInfo **info_p,
9388                                           uint32_t *count)
9389 {
9390         union spoolss_PrintProcessorInfo *info;
9391         WERROR result;
9392
9393         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9394         W_ERROR_HAVE_NO_MEMORY(info);
9395
9396         *count = 1;
9397
9398         result = fill_print_processor1(info, &info[0].info1, "winprint");
9399         if (!W_ERROR_IS_OK(result)) {
9400                 goto out;
9401         }
9402
9403  out:
9404         if (!W_ERROR_IS_OK(result)) {
9405                 TALLOC_FREE(info);
9406                 *count = 0;
9407                 return result;
9408         }
9409
9410         *info_p = info;
9411
9412         return WERR_OK;
9413 }
9414
9415 /****************************************************************
9416  _spoolss_EnumPrintProcessors
9417 ****************************************************************/
9418
9419 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9420                                     struct spoolss_EnumPrintProcessors *r)
9421 {
9422         WERROR result;
9423
9424         /* that's an [in out] buffer */
9425
9426         if (!r->in.buffer && (r->in.offered != 0)) {
9427                 return WERR_INVALID_PARAMETER;
9428         }
9429
9430         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9431
9432         /*
9433          * Enumerate the print processors ...
9434          *
9435          * Just reply with "winprint", to keep NT happy
9436          * and I can use my nice printer checker.
9437          */
9438
9439         *r->out.count = 0;
9440         *r->out.needed = 0;
9441         *r->out.info = NULL;
9442
9443         if (!get_short_archi(r->in.environment)) {
9444                 return WERR_INVALID_ENVIRONMENT;
9445         }
9446
9447         switch (r->in.level) {
9448         case 1:
9449                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9450                                                      r->out.count);
9451                 break;
9452         default:
9453                 return WERR_INVALID_LEVEL;
9454         }
9455
9456         if (!W_ERROR_IS_OK(result)) {
9457                 return result;
9458         }
9459
9460         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9461                                                      spoolss_EnumPrintProcessors,
9462                                                      *r->out.info, r->in.level,
9463                                                      *r->out.count);
9464         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9465         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9466
9467         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9468 }
9469
9470 /****************************************************************************
9471  fill_printprocdatatype1
9472 ****************************************************************************/
9473
9474 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9475                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9476                                       const char *name_array)
9477 {
9478         r->name_array = talloc_strdup(mem_ctx, name_array);
9479         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9480
9481         return WERR_OK;
9482 }
9483
9484 /****************************************************************************
9485  enumprintprocdatatypes level 1.
9486 ****************************************************************************/
9487
9488 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9489                                              union spoolss_PrintProcDataTypesInfo **info_p,
9490                                              uint32_t *count)
9491 {
9492         WERROR result;
9493         union spoolss_PrintProcDataTypesInfo *info;
9494
9495         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9496         W_ERROR_HAVE_NO_MEMORY(info);
9497
9498         *count = 1;
9499
9500         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9501         if (!W_ERROR_IS_OK(result)) {
9502                 goto out;
9503         }
9504
9505  out:
9506         if (!W_ERROR_IS_OK(result)) {
9507                 TALLOC_FREE(info);
9508                 *count = 0;
9509                 return result;
9510         }
9511
9512         *info_p = info;
9513
9514         return WERR_OK;
9515 }
9516
9517 /****************************************************************
9518  _spoolss_EnumPrintProcessorDataTypes
9519 ****************************************************************/
9520
9521 WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9522                                             struct spoolss_EnumPrintProcessorDataTypes *r)
9523 {
9524         WERROR result;
9525
9526         /* that's an [in out] buffer */
9527
9528         if (!r->in.buffer && (r->in.offered != 0)) {
9529                 return WERR_INVALID_PARAMETER;
9530         }
9531
9532         DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9533
9534         *r->out.count = 0;
9535         *r->out.needed = 0;
9536         *r->out.info = NULL;
9537
9538         if (r->in.print_processor_name == NULL ||
9539             !strequal(r->in.print_processor_name, "winprint")) {
9540                 return WERR_UNKNOWN_PRINTPROCESSOR;
9541         }
9542
9543         switch (r->in.level) {
9544         case 1:
9545                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9546                                                         r->out.count);
9547                 break;
9548         default:
9549                 return WERR_INVALID_LEVEL;
9550         }
9551
9552         if (!W_ERROR_IS_OK(result)) {
9553                 return result;
9554         }
9555
9556         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9557                                                      spoolss_EnumPrintProcessorDataTypes,
9558                                                      *r->out.info, r->in.level,
9559                                                      *r->out.count);
9560         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9561         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9562
9563         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9564 }
9565
9566 /****************************************************************************
9567  fill_monitor_1
9568 ****************************************************************************/
9569
9570 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9571                              struct spoolss_MonitorInfo1 *r,
9572                              const char *monitor_name)
9573 {
9574         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9575         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9576
9577         return WERR_OK;
9578 }
9579
9580 /****************************************************************************
9581  fill_monitor_2
9582 ****************************************************************************/
9583
9584 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9585                              struct spoolss_MonitorInfo2 *r,
9586                              const char *monitor_name,
9587                              const char *environment,
9588                              const char *dll_name)
9589 {
9590         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9591         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9592         r->environment                  = talloc_strdup(mem_ctx, environment);
9593         W_ERROR_HAVE_NO_MEMORY(r->environment);
9594         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9595         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9596
9597         return WERR_OK;
9598 }
9599
9600 /****************************************************************************
9601  enumprintmonitors level 1.
9602 ****************************************************************************/
9603
9604 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9605                                         union spoolss_MonitorInfo **info_p,
9606                                         uint32_t *count)
9607 {
9608         union spoolss_MonitorInfo *info;
9609         WERROR result = WERR_OK;
9610
9611         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9612         W_ERROR_HAVE_NO_MEMORY(info);
9613
9614         *count = 2;
9615
9616         result = fill_monitor_1(info, &info[0].info1,
9617                                 SPL_LOCAL_PORT);
9618         if (!W_ERROR_IS_OK(result)) {
9619                 goto out;
9620         }
9621
9622         result = fill_monitor_1(info, &info[1].info1,
9623                                 SPL_TCPIP_PORT);
9624         if (!W_ERROR_IS_OK(result)) {
9625                 goto out;
9626         }
9627
9628 out:
9629         if (!W_ERROR_IS_OK(result)) {
9630                 TALLOC_FREE(info);
9631                 *count = 0;
9632                 return result;
9633         }
9634
9635         *info_p = info;
9636
9637         return WERR_OK;
9638 }
9639
9640 /****************************************************************************
9641  enumprintmonitors level 2.
9642 ****************************************************************************/
9643
9644 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9645                                         union spoolss_MonitorInfo **info_p,
9646                                         uint32_t *count)
9647 {
9648         union spoolss_MonitorInfo *info;
9649         WERROR result = WERR_OK;
9650         const char *architecture;
9651
9652         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9653         W_ERROR_HAVE_NO_MEMORY(info);
9654
9655         *count = 2;
9656
9657         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
9658                                             "spoolss",
9659                                             "architecture",
9660                                             GLOBAL_SPOOLSS_ARCHITECTURE);
9661
9662         result = fill_monitor_2(info, &info[0].info2,
9663                                 SPL_LOCAL_PORT,
9664                                 architecture,
9665                                 "localmon.dll");
9666         if (!W_ERROR_IS_OK(result)) {
9667                 goto out;
9668         }
9669
9670         result = fill_monitor_2(info, &info[1].info2,
9671                                 SPL_TCPIP_PORT,
9672                                 architecture,
9673                                 "tcpmon.dll");
9674         if (!W_ERROR_IS_OK(result)) {
9675                 goto out;
9676         }
9677
9678 out:
9679         if (!W_ERROR_IS_OK(result)) {
9680                 TALLOC_FREE(info);
9681                 *count = 0;
9682                 return result;
9683         }
9684
9685         *info_p = info;
9686
9687         return WERR_OK;
9688 }
9689
9690 /****************************************************************
9691  _spoolss_EnumMonitors
9692 ****************************************************************/
9693
9694 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9695                              struct spoolss_EnumMonitors *r)
9696 {
9697         WERROR result;
9698
9699         /* that's an [in out] buffer */
9700
9701         if (!r->in.buffer && (r->in.offered != 0)) {
9702                 return WERR_INVALID_PARAMETER;
9703         }
9704
9705         DEBUG(5,("_spoolss_EnumMonitors\n"));
9706
9707         /*
9708          * Enumerate the print monitors ...
9709          *
9710          * Just reply with "Local Port", to keep NT happy
9711          * and I can use my nice printer checker.
9712          */
9713
9714         *r->out.count = 0;
9715         *r->out.needed = 0;
9716         *r->out.info = NULL;
9717
9718         switch (r->in.level) {
9719         case 1:
9720                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9721                                                    r->out.count);
9722                 break;
9723         case 2:
9724                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9725                                                    r->out.count);
9726                 break;
9727         default:
9728                 return WERR_INVALID_LEVEL;
9729         }
9730
9731         if (!W_ERROR_IS_OK(result)) {
9732                 return result;
9733         }
9734
9735         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9736                                                      spoolss_EnumMonitors,
9737                                                      *r->out.info, r->in.level,
9738                                                      *r->out.count);
9739         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9740         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9741
9742         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9743 }
9744
9745 /****************************************************************************
9746 ****************************************************************************/
9747
9748 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9749                              const print_queue_struct *queue,
9750                              int count, int snum,
9751                              struct spoolss_PrinterInfo2 *pinfo2,
9752                              uint32_t jobid,
9753                              int sysjob,
9754                              struct spoolss_JobInfo1 *r)
9755 {
9756         int i = 0;
9757         bool found = false;
9758
9759         for (i=0; i<count; i++) {
9760                 if (queue[i].sysjob == sysjob) {
9761                         found = true;
9762                         break;
9763                 }
9764         }
9765
9766         if (found == false) {
9767                 /* NT treats not found as bad param... yet another bad choice */
9768                 return WERR_INVALID_PARAMETER;
9769         }
9770
9771         return fill_job_info1(mem_ctx,
9772                               r,
9773                               &queue[i],
9774                               jobid,
9775                               i,
9776                               snum,
9777                               pinfo2);
9778 }
9779
9780 /****************************************************************************
9781 ****************************************************************************/
9782
9783 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9784                              const print_queue_struct *queue,
9785                              int count, int snum,
9786                              struct spoolss_PrinterInfo2 *pinfo2,
9787                              uint32_t jobid,
9788                              int sysjob,
9789                              struct spoolss_JobInfo2 *r)
9790 {
9791         int i = 0;
9792         bool found = false;
9793         struct spoolss_DeviceMode *devmode;
9794         WERROR result;
9795
9796         for (i=0; i<count; i++) {
9797                 if (queue[i].sysjob == sysjob) {
9798                         found = true;
9799                         break;
9800                 }
9801         }
9802
9803         if (found == false) {
9804                 /* NT treats not found as bad param... yet another bad
9805                    choice */
9806                 return WERR_INVALID_PARAMETER;
9807         }
9808
9809         /*
9810          * if the print job does not have a DEVMODE associated with it,
9811          * just use the one for the printer. A NULL devicemode is not
9812          *  a failure condition
9813          */
9814
9815         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9816         if (!devmode) {
9817                 result = spoolss_create_default_devmode(mem_ctx,
9818                                                 pinfo2->printername,
9819                                                 &devmode);
9820                 if (!W_ERROR_IS_OK(result)) {
9821                         DEBUG(3, ("Can't proceed w/o a devmode!\n"));
9822                         return result;
9823                 }
9824         }
9825
9826         return fill_job_info2(mem_ctx,
9827                               r,
9828                               &queue[i],
9829                               jobid,
9830                               i,
9831                               snum,
9832                               pinfo2,
9833                               devmode);
9834 }
9835
9836 /****************************************************************
9837  _spoolss_GetJob
9838 ****************************************************************/
9839
9840 WERROR _spoolss_GetJob(struct pipes_struct *p,
9841                        struct spoolss_GetJob *r)
9842 {
9843         WERROR result = WERR_OK;
9844         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9845         const char *svc_name;
9846         int sysjob;
9847         int snum;
9848         int count;
9849         struct tdb_print_db *pdb;
9850         print_queue_struct      *queue = NULL;
9851         print_status_struct prt_status;
9852
9853         /* that's an [in out] buffer */
9854
9855         if (!r->in.buffer && (r->in.offered != 0)) {
9856                 result = WERR_INVALID_PARAMETER;
9857                 goto err_jinfo_free;
9858         }
9859
9860         DEBUG(5,("_spoolss_GetJob\n"));
9861
9862         *r->out.needed = 0;
9863
9864         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9865                 result = WERR_INVALID_HANDLE;
9866                 goto err_jinfo_free;
9867         }
9868
9869         svc_name = lp_const_servicename(snum);
9870         if (svc_name == NULL) {
9871                 result = WERR_INVALID_PARAMETER;
9872                 goto err_jinfo_free;
9873         }
9874
9875         result = winreg_get_printer_internal(p->mem_ctx,
9876                                     get_session_info_system(),
9877                                     p->msg_ctx,
9878                                     svc_name,
9879                                     &pinfo2);
9880         if (!W_ERROR_IS_OK(result)) {
9881                 goto err_jinfo_free;
9882         }
9883
9884         pdb = get_print_db_byname(svc_name);
9885         if (pdb == NULL) {
9886                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9887                 result = WERR_INVALID_PARAMETER;
9888                 goto err_pinfo_free;
9889         }
9890
9891         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9892         release_print_db(pdb);
9893         if (sysjob == -1) {
9894                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9895                 result = WERR_INVALID_PARAMETER;
9896                 goto err_pinfo_free;
9897         }
9898
9899         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9900
9901         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9902                      count, prt_status.status, prt_status.message));
9903
9904         switch (r->in.level) {
9905         case 1:
9906                 result = getjob_level_1(p->mem_ctx,
9907                                         queue, count, snum, pinfo2,
9908                                         r->in.job_id, sysjob,
9909                                         &r->out.info->info1);
9910                 break;
9911         case 2:
9912                 result = getjob_level_2(p->mem_ctx,
9913                                         queue, count, snum, pinfo2,
9914                                         r->in.job_id, sysjob,
9915                                         &r->out.info->info2);
9916                 break;
9917         default:
9918                 result = WERR_INVALID_LEVEL;
9919                 break;
9920         }
9921
9922         SAFE_FREE(queue);
9923         TALLOC_FREE(pinfo2);
9924
9925         if (!W_ERROR_IS_OK(result)) {
9926                 goto err_jinfo_free;
9927         }
9928
9929         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9930                                                                                    r->in.level);
9931         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9932
9933         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9934
9935 err_pinfo_free:
9936         TALLOC_FREE(pinfo2);
9937 err_jinfo_free:
9938         TALLOC_FREE(r->out.info);
9939         return result;
9940 }
9941
9942 /****************************************************************
9943  _spoolss_GetPrinterDataEx
9944 ****************************************************************/
9945
9946 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9947                                  struct spoolss_GetPrinterDataEx *r)
9948 {
9949
9950         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9951         const char *printer;
9952         int                     snum = 0;
9953         WERROR result = WERR_OK;
9954         DATA_BLOB blob;
9955         enum winreg_Type val_type = REG_NONE;
9956         uint8_t *val_data = NULL;
9957         uint32_t val_size = 0;
9958         struct dcerpc_binding_handle *b;
9959         TALLOC_CTX *tmp_ctx;
9960
9961         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9962
9963         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9964                 r->in.key_name, r->in.value_name));
9965
9966         /* in case of problem, return some default values */
9967
9968         *r->out.needed  = 0;
9969         *r->out.type    = REG_NONE;
9970
9971         tmp_ctx = talloc_new(p->mem_ctx);
9972         if (!tmp_ctx) {
9973                 return WERR_NOT_ENOUGH_MEMORY;
9974         }
9975
9976         if (!Printer) {
9977                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9978                         OUR_HANDLE(r->in.handle)));
9979                 result = WERR_INVALID_HANDLE;
9980                 goto done;
9981         }
9982
9983         /* Is the handle to a printer or to the server? */
9984
9985         if (Printer->printer_type == SPLHND_SERVER) {
9986
9987                 union spoolss_PrinterData data;
9988
9989                 result = getprinterdata_printer_server(tmp_ctx,
9990                                                        r->in.value_name,
9991                                                        r->out.type,
9992                                                        &data);
9993                 if (!W_ERROR_IS_OK(result)) {
9994                         goto done;
9995                 }
9996
9997                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9998                                                   *r->out.type, &data);
9999                 if (!W_ERROR_IS_OK(result)) {
10000                         goto done;
10001                 }
10002
10003                 *r->out.needed = blob.length;
10004
10005                 if (r->in.offered >= *r->out.needed) {
10006                         memcpy(r->out.data, blob.data, blob.length);
10007                 }
10008
10009                 result = WERR_OK;
10010                 goto done;
10011         }
10012
10013         /* check to see if the keyname is valid */
10014         if (!strlen(r->in.key_name)) {
10015                 result = WERR_INVALID_PARAMETER;
10016                 goto done;
10017         }
10018
10019         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10020                 result = WERR_INVALID_HANDLE;
10021                 goto done;
10022         }
10023         printer = lp_const_servicename(snum);
10024
10025         result = winreg_printer_binding_handle(tmp_ctx,
10026                                                get_session_info_system(),
10027                                                p->msg_ctx,
10028                                                &b);
10029         if (!W_ERROR_IS_OK(result)) {
10030                 goto done;
10031         }
10032
10033         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
10034         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
10035             strequal(r->in.value_name, "ChangeId")) {
10036                 *r->out.type = REG_DWORD;
10037                 *r->out.needed = 4;
10038                 if (r->in.offered >= *r->out.needed) {
10039                         uint32_t changeid = 0;
10040
10041                         result = winreg_printer_get_changeid(tmp_ctx, b,
10042                                                              printer,
10043                                                              &changeid);
10044                         if (!W_ERROR_IS_OK(result)) {
10045                                 goto done;
10046                         }
10047
10048                         SIVAL(r->out.data, 0, changeid);
10049                         result = WERR_OK;
10050                 }
10051                 goto done;
10052         }
10053
10054         result = winreg_get_printer_dataex(tmp_ctx, b,
10055                                            printer,
10056                                            r->in.key_name,
10057                                            r->in.value_name,
10058                                            &val_type,
10059                                            &val_data,
10060                                            &val_size);
10061         if (!W_ERROR_IS_OK(result)) {
10062                 goto done;
10063         }
10064
10065         *r->out.needed = val_size;
10066         *r->out.type = val_type;
10067
10068         if (r->in.offered >= *r->out.needed) {
10069                 memcpy(r->out.data, val_data, val_size);
10070         }
10071
10072 done:
10073         /* NOTE: do not replace type when returning WERR_MORE_DATA */
10074
10075         if (W_ERROR_IS_OK(result)) {
10076                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10077         }
10078
10079         talloc_free(tmp_ctx);
10080         return result;
10081 }
10082
10083 /****************************************************************
10084  _spoolss_SetPrinterDataEx
10085 ****************************************************************/
10086
10087 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
10088                                  struct spoolss_SetPrinterDataEx *r)
10089 {
10090         const struct loadparm_substitution *lp_sub =
10091                 loadparm_s3_global_substitution();
10092         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
10093         int                     snum = 0;
10094         WERROR                  result = WERR_OK;
10095         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10096         char                    *oid_string;
10097         struct dcerpc_binding_handle *b;
10098         TALLOC_CTX *tmp_ctx;
10099
10100         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
10101
10102         /* From MSDN documentation of SetPrinterDataEx: pass request to
10103            SetPrinterData if key is "PrinterDriverData" */
10104
10105         if (!Printer) {
10106                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
10107                         OUR_HANDLE(r->in.handle)));
10108                 return WERR_INVALID_HANDLE;
10109         }
10110
10111         if (Printer->printer_type == SPLHND_SERVER) {
10112                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
10113                         "Not implemented for server handles yet\n"));
10114                 return WERR_INVALID_PARAMETER;
10115         }
10116
10117         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10118                 return WERR_INVALID_HANDLE;
10119         }
10120
10121         /*
10122          * Access check : NT returns "access denied" if you make a
10123          * SetPrinterData call without the necessary privilege.
10124          * we were originally returning OK if nothing changed
10125          * which made Win2k issue **a lot** of SetPrinterData
10126          * when connecting to a printer  --jerry
10127          */
10128
10129         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10130                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
10131                         "change denied by handle access permissions\n"));
10132                 return WERR_ACCESS_DENIED;
10133         }
10134
10135         tmp_ctx = talloc_new(p->mem_ctx);
10136         if (!tmp_ctx) {
10137                 return WERR_NOT_ENOUGH_MEMORY;
10138         }
10139
10140         result = winreg_printer_binding_handle(tmp_ctx,
10141                                                get_session_info_system(),
10142                                                p->msg_ctx,
10143                                                &b);
10144         if (!W_ERROR_IS_OK(result)) {
10145                 goto done;
10146         }
10147
10148         result = winreg_get_printer(tmp_ctx, b,
10149                                     lp_servicename(talloc_tos(), lp_sub, snum),
10150                                     &pinfo2);
10151         if (!W_ERROR_IS_OK(result)) {
10152                 goto done;
10153         }
10154
10155         /* check for OID in valuename */
10156
10157         oid_string = strchr(r->in.value_name, ',');
10158         if (oid_string) {
10159                 *oid_string = '\0';
10160                 oid_string++;
10161         }
10162
10163         /* save the registry data */
10164
10165         result = winreg_set_printer_dataex(tmp_ctx, b,
10166                                            pinfo2->sharename,
10167                                            r->in.key_name,
10168                                            r->in.value_name,
10169                                            r->in.type,
10170                                            r->in.data,
10171                                            r->in.offered);
10172
10173         if (W_ERROR_IS_OK(result)) {
10174                 /* save the OID if one was specified */
10175                 if (oid_string) {
10176                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
10177                                 r->in.key_name, SPOOL_OID_KEY);
10178                         if (!str) {
10179                                 result = WERR_NOT_ENOUGH_MEMORY;
10180                                 goto done;
10181                         }
10182
10183                         /*
10184                          * I'm not checking the status here on purpose.  Don't know
10185                          * if this is right, but I'm returning the status from the
10186                          * previous set_printer_dataex() call.  I have no idea if
10187                          * this is right.    --jerry
10188                          */
10189                         winreg_set_printer_dataex(tmp_ctx, b,
10190                                                   pinfo2->sharename,
10191                                                   str,
10192                                                   r->in.value_name,
10193                                                   REG_SZ,
10194                                                   (uint8_t *) oid_string,
10195                                                   strlen(oid_string) + 1);
10196                 }
10197
10198                 result = winreg_printer_update_changeid(tmp_ctx, b,
10199                                                         lp_const_servicename(snum));
10200
10201         }
10202
10203 done:
10204         talloc_free(tmp_ctx);
10205         return result;
10206 }
10207
10208 /****************************************************************
10209  _spoolss_DeletePrinterDataEx
10210 ****************************************************************/
10211
10212 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10213                                     struct spoolss_DeletePrinterDataEx *r)
10214 {
10215         const char *printer;
10216         int             snum=0;
10217         WERROR          status = WERR_OK;
10218         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10219
10220         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10221
10222         if (!Printer) {
10223                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10224                         "Invalid handle (%s:%u:%u).\n",
10225                         OUR_HANDLE(r->in.handle)));
10226                 return WERR_INVALID_HANDLE;
10227         }
10228
10229         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10230                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10231                         "printer properties change denied by handle\n"));
10232                 return WERR_ACCESS_DENIED;
10233         }
10234
10235         if (!r->in.value_name || !r->in.key_name) {
10236                 return WERR_NOT_ENOUGH_MEMORY;
10237         }
10238
10239         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10240                 return WERR_INVALID_HANDLE;
10241         }
10242         printer = lp_const_servicename(snum);
10243
10244         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10245                                               get_session_info_system(),
10246                                               p->msg_ctx,
10247                                               printer,
10248                                               r->in.key_name,
10249                                               r->in.value_name);
10250         if (W_ERROR_IS_OK(status)) {
10251                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
10252                                                         get_session_info_system(),
10253                                                         p->msg_ctx,
10254                                                         printer);
10255         }
10256
10257         return status;
10258 }
10259
10260 /****************************************************************
10261  _spoolss_EnumPrinterKey
10262 ****************************************************************/
10263
10264 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10265                                struct spoolss_EnumPrinterKey *r)
10266 {
10267         uint32_t        num_keys;
10268         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10269         int             snum = 0;
10270         WERROR          result = WERR_FILE_NOT_FOUND;
10271         const char **array = NULL;
10272         DATA_BLOB blob;
10273
10274         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10275
10276         if (!Printer) {
10277                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10278                         OUR_HANDLE(r->in.handle)));
10279                 return WERR_INVALID_HANDLE;
10280         }
10281
10282         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10283                 return WERR_INVALID_HANDLE;
10284         }
10285
10286         result = winreg_enum_printer_key_internal(p->mem_ctx,
10287                                          get_session_info_system(),
10288                                          p->msg_ctx,
10289                                          lp_const_servicename(snum),
10290                                          r->in.key_name,
10291                                          &num_keys,
10292                                          &array);
10293         if (!W_ERROR_IS_OK(result)) {
10294                 goto done;
10295         }
10296
10297         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10298                 result = WERR_NOT_ENOUGH_MEMORY;
10299                 goto done;
10300         }
10301
10302         *r->out._ndr_size = r->in.offered / 2;
10303         *r->out.needed = blob.length;
10304
10305         if (r->in.offered < *r->out.needed) {
10306                 result = WERR_MORE_DATA;
10307         } else {
10308                 result = WERR_OK;
10309                 r->out.key_buffer->string_array = array;
10310         }
10311
10312  done:
10313         if (!W_ERROR_IS_OK(result)) {
10314                 TALLOC_FREE(array);
10315                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10316                         *r->out.needed = 0;
10317                 }
10318         }
10319
10320         return result;
10321 }
10322
10323 /****************************************************************
10324  _spoolss_DeletePrinterKey
10325 ****************************************************************/
10326
10327 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10328                                  struct spoolss_DeletePrinterKey *r)
10329 {
10330         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10331         int                     snum=0;
10332         WERROR                  status;
10333         const char *printer;
10334         struct dcerpc_binding_handle *b;
10335         TALLOC_CTX *tmp_ctx;
10336
10337         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10338
10339         if (!Printer) {
10340                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10341                         OUR_HANDLE(r->in.handle)));
10342                 return WERR_INVALID_HANDLE;
10343         }
10344
10345         /* if keyname == NULL, return error */
10346         if ( !r->in.key_name )
10347                 return WERR_INVALID_PARAMETER;
10348
10349         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10350                 return WERR_INVALID_HANDLE;
10351         }
10352
10353         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10354                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10355                         "printer properties change denied by handle\n"));
10356                 return WERR_ACCESS_DENIED;
10357         }
10358
10359         printer = lp_const_servicename(snum);
10360
10361         tmp_ctx = talloc_new(p->mem_ctx);
10362         if (!tmp_ctx) {
10363                 return WERR_NOT_ENOUGH_MEMORY;
10364         }
10365
10366         status = winreg_printer_binding_handle(tmp_ctx,
10367                                                get_session_info_system(),
10368                                                p->msg_ctx,
10369                                                &b);
10370         if (!W_ERROR_IS_OK(status)) {
10371                 goto done;
10372         }
10373
10374         /* delete the key and all subkeys */
10375         status = winreg_delete_printer_key(tmp_ctx, b,
10376                                            printer,
10377                                            r->in.key_name);
10378         if (W_ERROR_IS_OK(status)) {
10379                 status = winreg_printer_update_changeid(tmp_ctx, b,
10380                                                         printer);
10381         }
10382
10383 done:
10384         talloc_free(tmp_ctx);
10385         return status;
10386 }
10387
10388 /****************************************************************
10389  _spoolss_EnumPrinterDataEx
10390 ****************************************************************/
10391
10392 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10393                                   struct spoolss_EnumPrinterDataEx *r)
10394 {
10395         uint32_t        count = 0;
10396         struct spoolss_PrinterEnumValues *info = NULL;
10397         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10398         int             snum;
10399         WERROR          result;
10400
10401         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10402
10403         *r->out.count = 0;
10404         *r->out.needed = 0;
10405         *r->out.info = NULL;
10406
10407         if (!Printer) {
10408                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10409                         OUR_HANDLE(r->in.handle)));
10410                 return WERR_INVALID_HANDLE;
10411         }
10412
10413         /*
10414          * first check for a keyname of NULL or "".  Win2k seems to send
10415          * this a lot and we should send back WERR_INVALID_PARAMETER
10416          * no need to spend time looking up the printer in this case.
10417          * --jerry
10418          */
10419
10420         if (!strlen(r->in.key_name)) {
10421                 result = WERR_INVALID_PARAMETER;
10422                 goto done;
10423         }
10424
10425         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10426                 return WERR_INVALID_HANDLE;
10427         }
10428
10429         /* now look for a match on the key name */
10430         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10431                                             get_session_info_system(),
10432                                             p->msg_ctx,
10433                                             lp_const_servicename(snum),
10434                                             r->in.key_name,
10435                                             &count,
10436                                             &info);
10437         if (!W_ERROR_IS_OK(result)) {
10438                 goto done;
10439         }
10440
10441         *r->out.count   = count;
10442         *r->out.info    = info;
10443
10444  done:
10445         if (!W_ERROR_IS_OK(result)) {
10446                 return result;
10447         }
10448
10449         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10450                                                spoolss_EnumPrinterDataEx,
10451                                                *r->out.info,
10452                                                *r->out.count);
10453         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10454         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10455
10456         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10457 }
10458
10459 /****************************************************************************
10460 ****************************************************************************/
10461
10462 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10463                                                  const char *servername,
10464                                                  const char *environment,
10465                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
10466 {
10467         WERROR werr;
10468         char *path = NULL;
10469
10470         werr = compose_spoolss_server_path(mem_ctx,
10471                                            servername,
10472                                            environment,
10473                                            SPOOLSS_PRTPROCS_PATH,
10474                                            &path);
10475         if (!W_ERROR_IS_OK(werr)) {
10476                 return werr;
10477         }
10478
10479         DEBUG(4,("print processor directory: [%s]\n", path));
10480
10481         r->directory_name = path;
10482
10483         return WERR_OK;
10484 }
10485
10486 /****************************************************************
10487  _spoolss_GetPrintProcessorDirectory
10488 ****************************************************************/
10489
10490 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10491                                            struct spoolss_GetPrintProcessorDirectory *r)
10492 {
10493         WERROR result;
10494         char *prnproc_share = NULL;
10495         bool prnproc_share_exists = false;
10496         int snum;
10497
10498         /* that's an [in out] buffer */
10499
10500         if (!r->in.buffer && (r->in.offered != 0)) {
10501                 result = WERR_INVALID_PARAMETER;
10502                 goto err_info_free;
10503         }
10504
10505         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10506                 r->in.level));
10507
10508         *r->out.needed = 0;
10509
10510         /* r->in.level is ignored */
10511
10512         /* We always should reply with a local print processor directory so that
10513          * users are not forced to have a [prnproc$] share on the Samba spoolss
10514          * server, if users decide to do so, lets announce it though - Guenther */
10515
10516         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10517         if (!prnproc_share) {
10518                 result = WERR_NOT_ENOUGH_MEMORY;
10519                 goto err_info_free;
10520         }
10521         if (snum != -1) {
10522                 prnproc_share_exists = true;
10523         }
10524
10525         result = getprintprocessordirectory_level_1(p->mem_ctx,
10526                                                     prnproc_share_exists ? r->in.server : NULL,
10527                                                     r->in.environment,
10528                                                     &r->out.info->info1);
10529         if (!W_ERROR_IS_OK(result)) {
10530                 goto err_info_free;
10531         }
10532
10533         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10534                                                                                    r->out.info, r->in.level);
10535         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10536
10537         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10538
10539 err_info_free:
10540         TALLOC_FREE(r->out.info);
10541         return result;
10542 }
10543
10544 /*******************************************************************
10545  ********************************************************************/
10546
10547 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10548                                const char *dllname)
10549 {
10550         enum ndr_err_code ndr_err;
10551         struct spoolss_MonitorUi ui;
10552
10553         ui.dll_name = dllname;
10554
10555         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10556                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10557         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10558                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10559         }
10560         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10561 }
10562
10563 /*******************************************************************
10564  Streams the monitor UI DLL name in UNICODE
10565 *******************************************************************/
10566
10567 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10568                                struct security_token *token, DATA_BLOB *in,
10569                                DATA_BLOB *out, uint32_t *needed)
10570 {
10571         const char *dllname = "tcpmonui.dll";
10572
10573         *needed = (strlen(dllname)+1) * 2;
10574
10575         if (out->length < *needed) {
10576                 return WERR_INSUFFICIENT_BUFFER;
10577         }
10578
10579         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10580                 return WERR_NOT_ENOUGH_MEMORY;
10581         }
10582
10583         return WERR_OK;
10584 }
10585
10586 /*******************************************************************
10587  ********************************************************************/
10588
10589 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10590                              struct spoolss_PortData1 *port1,
10591                              const DATA_BLOB *buf)
10592 {
10593         enum ndr_err_code ndr_err;
10594         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10595                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10596         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10597                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10598         }
10599         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10600 }
10601
10602 /*******************************************************************
10603  ********************************************************************/
10604
10605 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10606                              struct spoolss_PortData2 *port2,
10607                              const DATA_BLOB *buf)
10608 {
10609         enum ndr_err_code ndr_err;
10610         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10611                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10612         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10613                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10614         }
10615         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10616 }
10617
10618 /*******************************************************************
10619  Create a new TCP/IP port
10620 *******************************************************************/
10621
10622 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10623                              struct security_token *token, DATA_BLOB *in,
10624                              DATA_BLOB *out, uint32_t *needed)
10625 {
10626         struct spoolss_PortData1 port1;
10627         struct spoolss_PortData2 port2;
10628         char *device_uri = NULL;
10629         uint32_t version;
10630
10631         const char *portname;
10632         const char *hostaddress;
10633         const char *queue;
10634         uint32_t port_number;
10635         uint32_t protocol;
10636
10637         /* peek for spoolss_PortData version */
10638
10639         if (!in || (in->length < (128 + 4))) {
10640                 return WERR_GEN_FAILURE;
10641         }
10642
10643         version = IVAL(in->data, 128);
10644
10645         switch (version) {
10646                 case 1:
10647                         ZERO_STRUCT(port1);
10648
10649                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10650                                 return WERR_NOT_ENOUGH_MEMORY;
10651                         }
10652
10653                         portname        = port1.portname;
10654                         hostaddress     = port1.hostaddress;
10655                         queue           = port1.queue;
10656                         protocol        = port1.protocol;
10657                         port_number     = port1.port_number;
10658
10659                         break;
10660                 case 2:
10661                         ZERO_STRUCT(port2);
10662
10663                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10664                                 return WERR_NOT_ENOUGH_MEMORY;
10665                         }
10666
10667                         portname        = port2.portname;
10668                         hostaddress     = port2.hostaddress;
10669                         queue           = port2.queue;
10670                         protocol        = port2.protocol;
10671                         port_number     = port2.port_number;
10672
10673                         break;
10674                 default:
10675                         DEBUG(1,("xcvtcp_addport: "
10676                                 "unknown version of port_data: %d\n", version));
10677                         return WERR_UNKNOWN_PORT;
10678         }
10679
10680         /* create the device URI and call the add_port_hook() */
10681
10682         switch (protocol) {
10683         case PROTOCOL_RAWTCP_TYPE:
10684                 device_uri = talloc_asprintf(mem_ctx,
10685                                 "socket://%s:%d/", hostaddress,
10686                                 port_number);
10687                 break;
10688
10689         case PROTOCOL_LPR_TYPE:
10690                 device_uri = talloc_asprintf(mem_ctx,
10691                         "lpr://%s/%s", hostaddress, queue );
10692                 break;
10693
10694         default:
10695                 return WERR_UNKNOWN_PORT;
10696         }
10697
10698         if (!device_uri) {
10699                 return WERR_NOT_ENOUGH_MEMORY;
10700         }
10701
10702         return add_port_hook(mem_ctx, token, portname, device_uri);
10703 }
10704
10705 /*******************************************************************
10706 *******************************************************************/
10707
10708 struct xcv_api_table xcvtcp_cmds[] = {
10709         { "MonitorUI",  xcvtcp_monitorui },
10710         { "AddPort",    xcvtcp_addport},
10711         { NULL,         NULL }
10712 };
10713
10714 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10715                                      struct security_token *token, const char *command,
10716                                      DATA_BLOB *inbuf,
10717                                      DATA_BLOB *outbuf,
10718                                      uint32_t *needed )
10719 {
10720         int i;
10721
10722         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10723
10724         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10725                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10726                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10727         }
10728
10729         return WERR_INVALID_FUNCTION;
10730 }
10731
10732 /*******************************************************************
10733 *******************************************************************/
10734 #if 0   /* don't support management using the "Local Port" monitor */
10735
10736 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10737                                  struct security_token *token, DATA_BLOB *in,
10738                                  DATA_BLOB *out, uint32_t *needed)
10739 {
10740         const char *dllname = "localui.dll";
10741
10742         *needed = (strlen(dllname)+1) * 2;
10743
10744         if (out->length < *needed) {
10745                 return WERR_INSUFFICIENT_BUFFER;
10746         }
10747
10748         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10749                 return WERR_NOT_ENOUGH_MEMORY;
10750         }
10751
10752         return WERR_OK;
10753 }
10754
10755 /*******************************************************************
10756 *******************************************************************/
10757
10758 struct xcv_api_table xcvlocal_cmds[] = {
10759         { "MonitorUI",  xcvlocal_monitorui },
10760         { NULL,         NULL }
10761 };
10762 #else
10763 struct xcv_api_table xcvlocal_cmds[] = {
10764         { NULL,         NULL }
10765 };
10766 #endif
10767
10768
10769
10770 /*******************************************************************
10771 *******************************************************************/
10772
10773 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10774                                        struct security_token *token, const char *command,
10775                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10776                                        uint32_t *needed)
10777 {
10778         int i;
10779
10780         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10781
10782         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10783                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10784                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10785         }
10786         return WERR_INVALID_FUNCTION;
10787 }
10788
10789 /****************************************************************
10790  _spoolss_XcvData
10791 ****************************************************************/
10792
10793 WERROR _spoolss_XcvData(struct pipes_struct *p,
10794                         struct spoolss_XcvData *r)
10795 {
10796         struct dcesrv_call_state *dce_call = p->dce_call;
10797         struct auth_session_info *session_info =
10798                 dcesrv_call_session_info(dce_call);
10799         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10800         DATA_BLOB out_data = data_blob_null;
10801         WERROR werror;
10802
10803         if (!Printer) {
10804                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10805                         OUR_HANDLE(r->in.handle)));
10806                 return WERR_INVALID_HANDLE;
10807         }
10808
10809         /* Has to be a handle to the TCP/IP port monitor */
10810
10811         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10812                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10813                 return WERR_INVALID_HANDLE;
10814         }
10815
10816         /* requires administrative access to the server */
10817
10818         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10819                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10820                 return WERR_ACCESS_DENIED;
10821         }
10822
10823         /* Allocate the outgoing buffer */
10824
10825         if (r->in.out_data_size) {
10826                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10827                 if (out_data.data == NULL) {
10828                         return WERR_NOT_ENOUGH_MEMORY;
10829                 }
10830         }
10831
10832         switch ( Printer->printer_type ) {
10833         case SPLHND_PORTMON_TCP:
10834                 werror = process_xcvtcp_command(p->mem_ctx,
10835                                                 session_info->security_token,
10836                                                 r->in.function_name,
10837                                                 &r->in.in_data, &out_data,
10838                                                 r->out.needed);
10839                 break;
10840         case SPLHND_PORTMON_LOCAL:
10841                 werror = process_xcvlocal_command(p->mem_ctx,
10842                                                   session_info->security_token,
10843                                                   r->in.function_name,
10844                                                   &r->in.in_data, &out_data,
10845                                                   r->out.needed);
10846                 break;
10847         default:
10848                 werror = WERR_INVALID_PRINT_MONITOR;
10849         }
10850
10851         if (!W_ERROR_IS_OK(werror)) {
10852                 return werror;
10853         }
10854
10855         *r->out.status_code = 0;
10856
10857         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10858                 memcpy(r->out.out_data, out_data.data,
10859                         MIN(r->in.out_data_size, out_data.length));
10860         }
10861
10862         return WERR_OK;
10863 }
10864
10865 /****************************************************************
10866  _spoolss_AddPrintProcessor
10867 ****************************************************************/
10868
10869 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10870                                   struct spoolss_AddPrintProcessor *r)
10871 {
10872         /* for now, just indicate success and ignore the add.  We'll
10873            automatically set the winprint processor for printer
10874            entries later.  Used to debug the LexMark Optra S 1855 PCL
10875            driver --jerry */
10876
10877         return WERR_OK;
10878 }
10879
10880 /****************************************************************
10881  _spoolss_AddPort
10882 ****************************************************************/
10883
10884 WERROR _spoolss_AddPort(struct pipes_struct *p,
10885                         struct spoolss_AddPort *r)
10886 {
10887         /* do what w2k3 does */
10888
10889         return WERR_NOT_SUPPORTED;
10890 }
10891
10892 /****************************************************************
10893  _spoolss_GetPrinterDriver
10894 ****************************************************************/
10895
10896 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10897                                  struct spoolss_GetPrinterDriver *r)
10898 {
10899         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10900         return WERR_NOT_SUPPORTED;
10901 }
10902
10903 /****************************************************************
10904  _spoolss_ReadPrinter
10905 ****************************************************************/
10906
10907 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10908                             struct spoolss_ReadPrinter *r)
10909 {
10910         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10911         return WERR_NOT_SUPPORTED;
10912 }
10913
10914 /****************************************************************
10915  _spoolss_WaitForPrinterChange
10916 ****************************************************************/
10917
10918 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10919                                      struct spoolss_WaitForPrinterChange *r)
10920 {
10921         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10922         return WERR_NOT_SUPPORTED;
10923 }
10924
10925 /****************************************************************
10926  _spoolss_ConfigurePort
10927 ****************************************************************/
10928
10929 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10930                               struct spoolss_ConfigurePort *r)
10931 {
10932         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10933         return WERR_NOT_SUPPORTED;
10934 }
10935
10936 /****************************************************************
10937  _spoolss_DeletePort
10938 ****************************************************************/
10939
10940 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10941                            struct spoolss_DeletePort *r)
10942 {
10943         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10944         return WERR_NOT_SUPPORTED;
10945 }
10946
10947 /****************************************************************
10948  _spoolss_CreatePrinterIC
10949 ****************************************************************/
10950
10951 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10952                                 struct spoolss_CreatePrinterIC *r)
10953 {
10954         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10955         return WERR_NOT_SUPPORTED;
10956 }
10957
10958 /****************************************************************
10959  _spoolss_PlayGDIScriptOnPrinterIC
10960 ****************************************************************/
10961
10962 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10963                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10964 {
10965         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10966         return WERR_NOT_SUPPORTED;
10967 }
10968
10969 /****************************************************************
10970  _spoolss_DeletePrinterIC
10971 ****************************************************************/
10972
10973 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10974                                 struct spoolss_DeletePrinterIC *r)
10975 {
10976         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10977         return WERR_NOT_SUPPORTED;
10978 }
10979
10980 /****************************************************************
10981  _spoolss_AddPrinterConnection
10982 ****************************************************************/
10983
10984 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10985                                      struct spoolss_AddPrinterConnection *r)
10986 {
10987         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10988         return WERR_NOT_SUPPORTED;
10989 }
10990
10991 /****************************************************************
10992  _spoolss_DeletePrinterConnection
10993 ****************************************************************/
10994
10995 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10996                                         struct spoolss_DeletePrinterConnection *r)
10997 {
10998         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10999         return WERR_NOT_SUPPORTED;
11000 }
11001
11002 /****************************************************************
11003  _spoolss_PrinterMessageBox
11004 ****************************************************************/
11005
11006 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
11007                                   struct spoolss_PrinterMessageBox *r)
11008 {
11009         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11010         return WERR_NOT_SUPPORTED;
11011 }
11012
11013 /****************************************************************
11014  _spoolss_AddMonitor
11015 ****************************************************************/
11016
11017 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
11018                            struct spoolss_AddMonitor *r)
11019 {
11020         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11021         return WERR_NOT_SUPPORTED;
11022 }
11023
11024 /****************************************************************
11025  _spoolss_DeleteMonitor
11026 ****************************************************************/
11027
11028 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
11029                               struct spoolss_DeleteMonitor *r)
11030 {
11031         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11032         return WERR_NOT_SUPPORTED;
11033 }
11034
11035 /****************************************************************
11036  _spoolss_DeletePrintProcessor
11037 ****************************************************************/
11038
11039 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
11040                                      struct spoolss_DeletePrintProcessor *r)
11041 {
11042         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11043         return WERR_NOT_SUPPORTED;
11044 }
11045
11046 /****************************************************************
11047  _spoolss_AddPrintProvidor
11048 ****************************************************************/
11049
11050 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
11051                                  struct spoolss_AddPrintProvidor *r)
11052 {
11053         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11054         return WERR_NOT_SUPPORTED;
11055 }
11056
11057 /****************************************************************
11058  _spoolss_DeletePrintProvidor
11059 ****************************************************************/
11060
11061 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
11062                                     struct spoolss_DeletePrintProvidor *r)
11063 {
11064         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11065         return WERR_NOT_SUPPORTED;
11066 }
11067
11068 /****************************************************************
11069  _spoolss_FindFirstPrinterChangeNotification
11070 ****************************************************************/
11071
11072 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
11073                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
11074 {
11075         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11076         return WERR_NOT_SUPPORTED;
11077 }
11078
11079 /****************************************************************
11080  _spoolss_FindNextPrinterChangeNotification
11081 ****************************************************************/
11082
11083 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
11084                                                   struct spoolss_FindNextPrinterChangeNotification *r)
11085 {
11086         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11087         return WERR_NOT_SUPPORTED;
11088 }
11089
11090 /****************************************************************
11091  _spoolss_RouterFindFirstPrinterChangeNotificationOld
11092 ****************************************************************/
11093
11094 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
11095                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
11096 {
11097         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11098         return WERR_NOT_SUPPORTED;
11099 }
11100
11101 /****************************************************************
11102  _spoolss_ReplyOpenPrinter
11103 ****************************************************************/
11104
11105 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
11106                                  struct spoolss_ReplyOpenPrinter *r)
11107 {
11108         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11109         return WERR_NOT_SUPPORTED;
11110 }
11111
11112 /****************************************************************
11113  _spoolss_RouterReplyPrinter
11114 ****************************************************************/
11115
11116 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
11117                                    struct spoolss_RouterReplyPrinter *r)
11118 {
11119         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11120         return WERR_NOT_SUPPORTED;
11121 }
11122
11123 /****************************************************************
11124  _spoolss_ReplyClosePrinter
11125 ****************************************************************/
11126
11127 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
11128                                   struct spoolss_ReplyClosePrinter *r)
11129 {
11130         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11131         return WERR_NOT_SUPPORTED;
11132 }
11133
11134 /****************************************************************
11135  _spoolss_AddPortEx
11136 ****************************************************************/
11137
11138 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
11139                           struct spoolss_AddPortEx *r)
11140 {
11141         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11142         return WERR_NOT_SUPPORTED;
11143 }
11144
11145 /****************************************************************
11146  _spoolss_RouterFindFirstPrinterChangeNotification
11147 ****************************************************************/
11148
11149 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
11150                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
11151 {
11152         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11153         return WERR_NOT_SUPPORTED;
11154 }
11155
11156 /****************************************************************
11157  _spoolss_SpoolerInit
11158 ****************************************************************/
11159
11160 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
11161                             struct spoolss_SpoolerInit *r)
11162 {
11163         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11164         return WERR_NOT_SUPPORTED;
11165 }
11166
11167 /****************************************************************
11168  _spoolss_ResetPrinterEx
11169 ****************************************************************/
11170
11171 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
11172                                struct spoolss_ResetPrinterEx *r)
11173 {
11174         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11175         return WERR_NOT_SUPPORTED;
11176 }
11177
11178 /****************************************************************
11179  _spoolss_RouterReplyPrinterEx
11180 ****************************************************************/
11181
11182 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
11183                                      struct spoolss_RouterReplyPrinterEx *r)
11184 {
11185         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11186         return WERR_NOT_SUPPORTED;
11187 }
11188
11189 /****************************************************************
11190  _spoolss_44
11191 ****************************************************************/
11192
11193 WERROR _spoolss_44(struct pipes_struct *p,
11194                    struct spoolss_44 *r)
11195 {
11196         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11197         return WERR_NOT_SUPPORTED;
11198 }
11199
11200 /****************************************************************
11201  _spoolss_SetPort
11202 ****************************************************************/
11203
11204 WERROR _spoolss_SetPort(struct pipes_struct *p,
11205                         struct spoolss_SetPort *r)
11206 {
11207         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11208         return WERR_NOT_SUPPORTED;
11209 }
11210
11211 /****************************************************************
11212  _spoolss_4a
11213 ****************************************************************/
11214
11215 WERROR _spoolss_4a(struct pipes_struct *p,
11216                    struct spoolss_4a *r)
11217 {
11218         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11219         return WERR_NOT_SUPPORTED;
11220 }
11221
11222 /****************************************************************
11223  _spoolss_4b
11224 ****************************************************************/
11225
11226 WERROR _spoolss_4b(struct pipes_struct *p,
11227                    struct spoolss_4b *r)
11228 {
11229         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11230         return WERR_NOT_SUPPORTED;
11231 }
11232
11233 /****************************************************************
11234  _spoolss_4c
11235 ****************************************************************/
11236
11237 WERROR _spoolss_4c(struct pipes_struct *p,
11238                    struct spoolss_4c *r)
11239 {
11240         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11241         return WERR_NOT_SUPPORTED;
11242 }
11243
11244 /****************************************************************
11245  _spoolss_53
11246 ****************************************************************/
11247
11248 WERROR _spoolss_53(struct pipes_struct *p,
11249                    struct spoolss_53 *r)
11250 {
11251         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11252         return WERR_NOT_SUPPORTED;
11253 }
11254
11255 /****************************************************************
11256  _spoolss_AddPerMachineConnection
11257 ****************************************************************/
11258
11259 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11260                                         struct spoolss_AddPerMachineConnection *r)
11261 {
11262         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11263         return WERR_NOT_SUPPORTED;
11264 }
11265
11266 /****************************************************************
11267  _spoolss_DeletePerMachineConnection
11268 ****************************************************************/
11269
11270 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11271                                            struct spoolss_DeletePerMachineConnection *r)
11272 {
11273         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11274         return WERR_NOT_SUPPORTED;
11275 }
11276
11277 /****************************************************************
11278  _spoolss_EnumPerMachineConnections
11279 ****************************************************************/
11280
11281 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11282                                           struct spoolss_EnumPerMachineConnections *r)
11283 {
11284         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11285         return WERR_NOT_SUPPORTED;
11286 }
11287
11288 /****************************************************************
11289  _spoolss_5a
11290 ****************************************************************/
11291
11292 WERROR _spoolss_5a(struct pipes_struct *p,
11293                    struct spoolss_5a *r)
11294 {
11295         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11296         return WERR_NOT_SUPPORTED;
11297 }
11298
11299 /****************************************************************
11300  _spoolss_5b
11301 ****************************************************************/
11302
11303 WERROR _spoolss_5b(struct pipes_struct *p,
11304                    struct spoolss_5b *r)
11305 {
11306         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11307         return WERR_NOT_SUPPORTED;
11308 }
11309
11310 /****************************************************************
11311  _spoolss_5c
11312 ****************************************************************/
11313
11314 WERROR _spoolss_5c(struct pipes_struct *p,
11315                    struct spoolss_5c *r)
11316 {
11317         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11318         return WERR_NOT_SUPPORTED;
11319 }
11320
11321 /****************************************************************
11322  _spoolss_5d
11323 ****************************************************************/
11324
11325 WERROR _spoolss_5d(struct pipes_struct *p,
11326                    struct spoolss_5d *r)
11327 {
11328         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11329         return WERR_NOT_SUPPORTED;
11330 }
11331
11332 /****************************************************************
11333  _spoolss_5e
11334 ****************************************************************/
11335
11336 WERROR _spoolss_5e(struct pipes_struct *p,
11337                    struct spoolss_5e *r)
11338 {
11339         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11340         return WERR_NOT_SUPPORTED;
11341 }
11342
11343 /****************************************************************
11344  _spoolss_5f
11345 ****************************************************************/
11346
11347 WERROR _spoolss_5f(struct pipes_struct *p,
11348                    struct spoolss_5f *r)
11349 {
11350         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11351         return WERR_NOT_SUPPORTED;
11352 }
11353
11354 /****************************************************************
11355  _spoolss_60
11356 ****************************************************************/
11357
11358 WERROR _spoolss_60(struct pipes_struct *p,
11359                    struct spoolss_60 *r)
11360 {
11361         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11362         return WERR_NOT_SUPPORTED;
11363 }
11364
11365 /****************************************************************
11366  _spoolss_SendRecvBidiData
11367 ****************************************************************/
11368
11369 WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11370                                  struct spoolss_SendRecvBidiData *r)
11371 {
11372         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11373         return WERR_NOT_SUPPORTED;
11374 }
11375
11376 /****************************************************************
11377  _spoolss_62
11378 ****************************************************************/
11379
11380 WERROR _spoolss_62(struct pipes_struct *p,
11381                    struct spoolss_62 *r)
11382 {
11383         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11384         return WERR_NOT_SUPPORTED;
11385 }
11386
11387 /****************************************************************
11388  _spoolss_63
11389 ****************************************************************/
11390
11391 WERROR _spoolss_63(struct pipes_struct *p,
11392                    struct spoolss_63 *r)
11393 {
11394         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11395         return WERR_NOT_SUPPORTED;
11396 }
11397
11398 /****************************************************************
11399  _spoolss_64
11400 ****************************************************************/
11401
11402 WERROR _spoolss_64(struct pipes_struct *p,
11403                    struct spoolss_64 *r)
11404 {
11405         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11406         return WERR_NOT_SUPPORTED;
11407 }
11408
11409 /****************************************************************
11410  _spoolss_65
11411 ****************************************************************/
11412
11413 WERROR _spoolss_65(struct pipes_struct *p,
11414                    struct spoolss_65 *r)
11415 {
11416         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11417         return WERR_NOT_SUPPORTED;
11418 }
11419
11420 /****************************************************************
11421  _spoolss_GetCorePrinterDrivers
11422 ****************************************************************/
11423
11424 HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11425                                        struct spoolss_GetCorePrinterDrivers *r)
11426 {
11427         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11428         return HRES_ERROR_NOT_SUPPORTED;
11429 }
11430
11431 /****************************************************************
11432  _spoolss_67
11433 ****************************************************************/
11434
11435 WERROR _spoolss_67(struct pipes_struct *p,
11436                    struct spoolss_67 *r)
11437 {
11438         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11439         return WERR_NOT_SUPPORTED;
11440 }
11441
11442 /****************************************************************
11443  _spoolss_GetPrinterDriverPackagePath
11444 ****************************************************************/
11445
11446 HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11447                                              struct spoolss_GetPrinterDriverPackagePath *r)
11448 {
11449         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11450         return HRES_ERROR_NOT_SUPPORTED;
11451 }
11452
11453 /****************************************************************
11454  _spoolss_69
11455 ****************************************************************/
11456
11457 WERROR _spoolss_69(struct pipes_struct *p,
11458                    struct spoolss_69 *r)
11459 {
11460         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11461         return WERR_NOT_SUPPORTED;
11462 }
11463
11464 /****************************************************************
11465  _spoolss_6a
11466 ****************************************************************/
11467
11468 WERROR _spoolss_6a(struct pipes_struct *p,
11469                    struct spoolss_6a *r)
11470 {
11471         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11472         return WERR_NOT_SUPPORTED;
11473 }
11474
11475 /****************************************************************
11476  _spoolss_6b
11477 ****************************************************************/
11478
11479 WERROR _spoolss_6b(struct pipes_struct *p,
11480                    struct spoolss_6b *r)
11481 {
11482         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11483         return WERR_NOT_SUPPORTED;
11484 }
11485
11486 /****************************************************************
11487  _spoolss_6c
11488 ****************************************************************/
11489
11490 WERROR _spoolss_6c(struct pipes_struct *p,
11491                    struct spoolss_6c *r)
11492 {
11493         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11494         return WERR_NOT_SUPPORTED;
11495 }
11496
11497 /****************************************************************
11498  _spoolss_6d
11499 ****************************************************************/
11500
11501 WERROR _spoolss_6d(struct pipes_struct *p,
11502                    struct spoolss_6d *r)
11503 {
11504         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11505         return WERR_NOT_SUPPORTED;
11506 }
11507
11508 /****************************************************************
11509  _spoolss_GetJobNamedPropertyValue
11510 ****************************************************************/
11511
11512 WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11513                                          struct spoolss_GetJobNamedPropertyValue *r)
11514 {
11515         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11516         return WERR_NOT_SUPPORTED;
11517 }
11518
11519 /****************************************************************
11520  _spoolss_SetJobNamedProperty
11521 ****************************************************************/
11522
11523 WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11524                                     struct spoolss_SetJobNamedProperty *r)
11525 {
11526         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11527         return WERR_NOT_SUPPORTED;
11528 }
11529
11530 /****************************************************************
11531  _spoolss_DeleteJobNamedProperty
11532 ****************************************************************/
11533
11534 WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11535                                        struct spoolss_DeleteJobNamedProperty *r)
11536 {
11537         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11538         return WERR_NOT_SUPPORTED;
11539 }
11540
11541 /****************************************************************
11542  _spoolss_EnumJobNamedProperties
11543 ****************************************************************/
11544
11545 WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11546                                        struct spoolss_EnumJobNamedProperties *r)
11547 {
11548         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11549         return WERR_NOT_SUPPORTED;
11550 }
11551
11552 /****************************************************************
11553  _spoolss_72
11554 ****************************************************************/
11555
11556 WERROR _spoolss_72(struct pipes_struct *p,
11557                    struct spoolss_72 *r)
11558 {
11559         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11560         return WERR_NOT_SUPPORTED;
11561 }
11562
11563 /****************************************************************
11564  _spoolss_73
11565 ****************************************************************/
11566
11567 WERROR _spoolss_73(struct pipes_struct *p,
11568                    struct spoolss_73 *r)
11569 {
11570         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11571         return WERR_NOT_SUPPORTED;
11572 }
11573
11574 /****************************************************************
11575  _spoolss_RpcLogJobInfoForBranchOffice
11576 ****************************************************************/
11577
11578 WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11579                                           struct spoolss_LogJobInfoForBranchOffice *r)
11580 {
11581         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11582         return WERR_NOT_SUPPORTED;
11583 }
11584
11585 static NTSTATUS spoolss__op_init_server(struct dcesrv_context *dce_ctx,
11586                 const struct dcesrv_endpoint_server *ep_server);
11587
11588 static NTSTATUS spoolss__op_shutdown_server(struct dcesrv_context *dce_ctx,
11589                 const struct dcesrv_endpoint_server *ep_server);
11590
11591 #define DCESRV_INTERFACE_SPOOLSS_INIT_SERVER \
11592         spoolss_init_server
11593
11594 #define DCESRV_INTERFACE_SPOOLSS_SHUTDOWN_SERVER \
11595         spoolss_shutdown_server
11596
11597 static NTSTATUS spoolss_init_server(struct dcesrv_context *dce_ctx,
11598                 const struct dcesrv_endpoint_server *ep_server)
11599 {
11600         struct messaging_context *msg_ctx = global_messaging_context();
11601         bool ok;
11602
11603         /*
11604          * Migrate the printers first.
11605          */
11606         ok = nt_printing_tdb_migrate(msg_ctx);
11607         if (!ok) {
11608                 return NT_STATUS_UNSUCCESSFUL;
11609         }
11610
11611         return spoolss__op_init_server(dce_ctx, ep_server);
11612 }
11613
11614 static NTSTATUS spoolss_shutdown_server(struct dcesrv_context *dce_ctx,
11615                 const struct dcesrv_endpoint_server *ep_server)
11616 {
11617         srv_spoolss_cleanup();
11618
11619         return spoolss__op_shutdown_server(dce_ctx, ep_server);
11620 }
11621
11622 /* include the generated boilerplate */
11623 #include "librpc/gen_ndr/ndr_spoolss_scompat.c"