s3:spoolss: Fix size types
[metze/samba/wip.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
59 #include "rpc_server/spoolss/srv_spoolss_handle.h"
60
61 /* macros stolen from s4 spoolss server */
62 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
63         ((info)?ndr_size_##fn(info, level, 0):0)
64
65 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
66         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
67
68 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
69         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
70
71 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
72
73 #undef DBGC_CLASS
74 #define DBGC_CLASS DBGC_RPC_SRV
75
76 #ifndef MAX_OPEN_PRINTER_EXS
77 #define MAX_OPEN_PRINTER_EXS 50
78 #endif
79
80 #define GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT 5
81 #define GLOBAL_SPOOLSS_OS_MINOR_DEFAULT 2
82 #define GLOBAL_SPOOLSS_OS_BUILD_DEFAULT 3790
83 #define GLOBAL_SPOOLSS_ARCHITECTURE SPOOLSS_ARCHITECTURE_x64
84
85 static struct printer_handle *printers_list;
86
87 struct printer_session_counter {
88         struct printer_session_counter *next;
89         struct printer_session_counter *prev;
90
91         int snum;
92         uint32_t counter;
93 };
94
95 static struct printer_session_counter *counter_list;
96
97 struct notify_back_channel {
98         struct notify_back_channel *prev, *next;
99
100         /* associated client */
101         struct sockaddr_storage client_address;
102
103         /* print notify back-channel pipe handle*/
104         struct rpc_pipe_client *cli_pipe;
105         struct cli_state *cli;
106         uint32_t active_connections;
107 };
108
109 static struct notify_back_channel *back_channels;
110
111 /* Map generic permissions to printer object specific permissions */
112
113 const struct standard_mapping printer_std_mapping = {
114         PRINTER_READ,
115         PRINTER_WRITE,
116         PRINTER_EXECUTE,
117         PRINTER_ALL_ACCESS
118 };
119
120 /* Map generic permissions to print server object specific permissions */
121
122 const struct standard_mapping printserver_std_mapping = {
123         SERVER_READ,
124         SERVER_WRITE,
125         SERVER_EXECUTE,
126         SERVER_ALL_ACCESS
127 };
128
129 /* API table for Xcv Monitor functions */
130
131 struct xcv_api_table {
132         const char *name;
133         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
134 };
135
136 static void prune_printername_cache(void);
137
138 /********************************************************************
139  * Canonicalize servername.
140  ********************************************************************/
141
142 static const char *canon_servername(const char *servername)
143 {
144         const char *pservername = servername;
145
146         if (servername == NULL) {
147                 return "";
148         }
149
150         while (*pservername == '\\') {
151                 pservername++;
152         }
153         return pservername;
154 }
155
156 /* translate between internal status numbers and NT status numbers */
157 static int nt_printj_status(int v)
158 {
159         switch (v) {
160         case LPQ_QUEUED:
161                 return 0;
162         case LPQ_PAUSED:
163                 return JOB_STATUS_PAUSED;
164         case LPQ_SPOOLING:
165                 return JOB_STATUS_SPOOLING;
166         case LPQ_PRINTING:
167                 return JOB_STATUS_PRINTING;
168         case LPQ_ERROR:
169                 return JOB_STATUS_ERROR;
170         case LPQ_DELETING:
171                 return JOB_STATUS_DELETING;
172         case LPQ_OFFLINE:
173                 return JOB_STATUS_OFFLINE;
174         case LPQ_PAPEROUT:
175                 return JOB_STATUS_PAPEROUT;
176         case LPQ_PRINTED:
177                 return JOB_STATUS_PRINTED;
178         case LPQ_DELETED:
179                 return JOB_STATUS_DELETED;
180         case LPQ_BLOCKED:
181                 return JOB_STATUS_BLOCKED_DEVQ;
182         case LPQ_USER_INTERVENTION:
183                 return JOB_STATUS_USER_INTERVENTION;
184         }
185         return 0;
186 }
187
188 static int nt_printq_status(int v)
189 {
190         switch (v) {
191         case LPQ_PAUSED:
192                 return PRINTER_STATUS_PAUSED;
193         case LPQ_QUEUED:
194         case LPQ_SPOOLING:
195         case LPQ_PRINTING:
196                 return 0;
197         }
198         return 0;
199 }
200
201 /***************************************************************************
202  Disconnect from the client
203 ****************************************************************************/
204
205 static void srv_spoolss_replycloseprinter(int snum,
206                                           struct printer_handle *prn_hnd)
207 {
208         WERROR result;
209         NTSTATUS status;
210
211         /*
212          * Tell the specific printing tdb we no longer want messages for this printer
213          * by deregistering our PID.
214          */
215
216         if (!print_notify_deregister_pid(snum)) {
217                 DEBUG(0, ("Failed to register our pid for printer %s\n",
218                           lp_const_servicename(snum)));
219         }
220
221         /* weird if the test succeeds !!! */
222         if (prn_hnd->notify.cli_chan == NULL ||
223             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
224             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
225             prn_hnd->notify.cli_chan->active_connections == 0) {
226                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
227                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
228                 TALLOC_FREE(prn_hnd->notify.cli_chan);
229                 return;
230         }
231
232         status = dcerpc_spoolss_ReplyClosePrinter(
233                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
234                                         talloc_tos(),
235                                         &prn_hnd->notify.cli_hnd,
236                                         &result);
237         if (!NT_STATUS_IS_OK(status)) {
238                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
239                           nt_errstr(status)));
240                 result = ntstatus_to_werror(status);
241         } else if (!W_ERROR_IS_OK(result)) {
242                 DEBUG(0, ("reply_close_printer failed [%s].\n",
243                           win_errstr(result)));
244         }
245
246         /* if it's the last connection, deconnect the IPC$ share */
247         if (prn_hnd->notify.cli_chan->active_connections == 1) {
248
249                 cli_shutdown(prn_hnd->notify.cli_chan->cli);
250                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
251                 TALLOC_FREE(prn_hnd->notify.cli_chan);
252
253                 if (prn_hnd->notify.msg_ctx != NULL) {
254                         messaging_deregister(prn_hnd->notify.msg_ctx,
255                                              MSG_PRINTER_NOTIFY2, NULL);
256                 }
257         }
258
259         if (prn_hnd->notify.cli_chan) {
260                 prn_hnd->notify.cli_chan->active_connections--;
261                 prn_hnd->notify.cli_chan = NULL;
262         }
263 }
264
265 /****************************************************************************
266  Functions to free a printer entry datastruct.
267 ****************************************************************************/
268
269 static int printer_entry_destructor(struct printer_handle *Printer)
270 {
271         if (Printer->notify.cli_chan != NULL &&
272             Printer->notify.cli_chan->active_connections > 0) {
273                 int snum = -1;
274
275                 switch(Printer->printer_type) {
276                 case SPLHND_SERVER:
277                         srv_spoolss_replycloseprinter(snum, Printer);
278                         break;
279
280                 case SPLHND_PRINTER:
281                         snum = print_queue_snum(Printer->sharename);
282                         if (snum != -1) {
283                                 srv_spoolss_replycloseprinter(snum, Printer);
284                         }
285                         break;
286                 default:
287                         break;
288                 }
289         }
290
291         Printer->notify.flags=0;
292         Printer->notify.options=0;
293         Printer->notify.localmachine[0]='\0';
294         Printer->notify.printerlocal=0;
295         TALLOC_FREE(Printer->notify.option);
296         TALLOC_FREE(Printer->devmode);
297
298         /* Remove from the internal list. */
299         DLIST_REMOVE(printers_list, Printer);
300         return 0;
301 }
302
303 /****************************************************************************
304   find printer index by handle
305 ****************************************************************************/
306
307 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
308                                                         struct policy_handle *hnd)
309 {
310         struct printer_handle *find_printer = NULL;
311
312         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
313                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
314                 return NULL;
315         }
316
317         return find_printer;
318 }
319
320 /****************************************************************************
321  Close printer index by handle.
322 ****************************************************************************/
323
324 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
325 {
326         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
327
328         if (!Printer) {
329                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
330                         OUR_HANDLE(hnd)));
331                 return false;
332         }
333
334         close_policy_hnd(p, hnd);
335
336         return true;
337 }
338
339 /****************************************************************************
340  Delete a printer given a handle.
341 ****************************************************************************/
342
343 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
344                                   const char *sharename,
345                                   struct messaging_context *msg_ctx)
346 {
347         char *cmd = lp_deleteprinter_command(talloc_tos());
348         char *command = NULL;
349         int ret;
350         bool is_print_op = false;
351
352         /* can't fail if we don't try */
353
354         if ( !*cmd )
355                 return WERR_OK;
356
357         command = talloc_asprintf(ctx,
358                         "%s \"%s\"",
359                         cmd, sharename);
360         if (!command) {
361                 return WERR_NOT_ENOUGH_MEMORY;
362         }
363         if ( token )
364                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
365
366         DEBUG(10,("Running [%s]\n", command));
367
368         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
369
370         if ( is_print_op )
371                 become_root();
372
373         ret = smbrun(command, NULL, NULL);
374         if (ret == 0) {
375                 /* Tell everyone we updated smb.conf. */
376                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
377         }
378
379         if ( is_print_op )
380                 unbecome_root();
381
382         /********** END SePrintOperatorPrivlege BLOCK **********/
383
384         DEBUGADD(10,("returned [%d]\n", ret));
385
386         TALLOC_FREE(command);
387
388         if (ret != 0)
389                 return WERR_INVALID_HANDLE; /* What to return here? */
390
391         return WERR_OK;
392 }
393
394 /****************************************************************************
395  Delete a printer given a handle.
396 ****************************************************************************/
397
398 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
399 {
400         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
401         WERROR result;
402
403         if (!Printer) {
404                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
405                         OUR_HANDLE(hnd)));
406                 return WERR_INVALID_HANDLE;
407         }
408
409         /*
410          * It turns out that Windows allows delete printer on a handle
411          * opened by an admin user, then used on a pipe handle created
412          * by an anonymous user..... but they're working on security.... riiight !
413          * JRA.
414          */
415
416         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
417                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
418                 return WERR_ACCESS_DENIED;
419         }
420
421         /* this does not need a become root since the access check has been
422            done on the handle already */
423
424         result = winreg_delete_printer_key_internal(p->mem_ctx,
425                                            get_session_info_system(),
426                                            p->msg_ctx,
427                                            Printer->sharename,
428                                            "");
429         if (!W_ERROR_IS_OK(result)) {
430                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
431                 return WERR_INVALID_HANDLE;
432         }
433
434         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
435                                      Printer->sharename, p->msg_ctx);
436         if (!W_ERROR_IS_OK(result)) {
437                 return result;
438         }
439         prune_printername_cache();
440         return WERR_OK;
441 }
442
443 /****************************************************************************
444  Return the snum of a printer corresponding to an handle.
445 ****************************************************************************/
446
447 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
448                              int *number, struct share_params **params)
449 {
450         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
451
452         if (!Printer) {
453                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
454                         OUR_HANDLE(hnd)));
455                 return false;
456         }
457
458         switch (Printer->printer_type) {
459                 case SPLHND_PRINTER:
460                         DEBUG(4,("short name:%s\n", Printer->sharename));
461                         *number = print_queue_snum(Printer->sharename);
462                         return (*number != -1);
463                 case SPLHND_SERVER:
464                         return false;
465                 default:
466                         return false;
467         }
468 }
469
470 /****************************************************************************
471  Set printer handle type.
472  Check if it's \\server or \\server\printer
473 ****************************************************************************/
474
475 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
476 {
477         DEBUG(3,("Setting printer type=%s\n", handlename));
478
479         /* it's a print server */
480         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
481                 DEBUGADD(4,("Printer is a print server\n"));
482                 Printer->printer_type = SPLHND_SERVER;
483         }
484         /* it's a printer (set_printer_hnd_name() will handle port monitors */
485         else {
486                 DEBUGADD(4,("Printer is a printer\n"));
487                 Printer->printer_type = SPLHND_PRINTER;
488         }
489
490         return true;
491 }
492
493 static void prune_printername_cache_fn(const char *key, const char *value,
494                                        time_t timeout, void *private_data)
495 {
496         gencache_del(key);
497 }
498
499 static void prune_printername_cache(void)
500 {
501         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
502 }
503
504 /****************************************************************************
505  Set printer handle name..  Accept names like \\server, \\server\printer,
506  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
507  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
508  XcvDataPort() interface.
509 ****************************************************************************/
510
511 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
512                                    const struct auth_session_info *session_info,
513                                    struct messaging_context *msg_ctx,
514                                    struct printer_handle *Printer,
515                                    const char *handlename)
516 {
517         int snum;
518         int n_services=lp_numservices();
519         char *aprinter;
520         const char *printername;
521         const char *servername = NULL;
522         fstring sname;
523         bool found = false;
524         struct spoolss_PrinterInfo2 *info2 = NULL;
525         WERROR result;
526         char *p;
527
528         /*
529          * Hopefully nobody names his printers like this. Maybe \ or ,
530          * are illegal in printer names even?
531          */
532         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
533         char *cache_key;
534         char *tmp;
535
536         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
537                 (unsigned long)strlen(handlename)));
538
539         aprinter = discard_const_p(char, handlename);
540         if ( *handlename == '\\' ) {
541                 servername = canon_servername(handlename);
542                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
543                         *aprinter = '\0';
544                         aprinter++;
545                 }
546                 if (!is_myname_or_ipaddr(servername)) {
547                         return WERR_INVALID_PRINTER_NAME;
548                 }
549                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
550                 if (Printer->servername == NULL) {
551                         return WERR_NOT_ENOUGH_MEMORY;
552                 }
553         }
554
555         if (Printer->printer_type == SPLHND_SERVER) {
556                 return WERR_OK;
557         }
558
559         if (Printer->printer_type != SPLHND_PRINTER) {
560                 return WERR_INVALID_HANDLE;
561         }
562
563         DEBUGADD(5, ("searching for [%s]\n", aprinter));
564
565         p = strchr(aprinter, ',');
566         if (p != NULL) {
567                 char *p2 = p;
568                 p++;
569                 if (*p == ' ') {
570                         p++;
571                 }
572                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
573                         *p2 = '\0';
574                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
575                         *p2 = '\0';
576                 }
577         }
578
579         if (p) {
580                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
581         }
582
583         /* check for the Port Monitor Interface */
584         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
585                 Printer->printer_type = SPLHND_PORTMON_TCP;
586                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
587                 found = true;
588         }
589         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
590                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
591                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
592                 found = true;
593         }
594
595         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
596         if (cache_key == NULL) {
597                 return WERR_NOT_ENOUGH_MEMORY;
598         }
599
600         /*
601          * With hundreds of printers, the "for" loop iterating all
602          * shares can be quite expensive, as it is done on every
603          * OpenPrinter. The loop maps "aprinter" to "sname", the
604          * result of which we cache in gencache.
605          */
606         if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
607                 found = (strcmp(tmp, printer_not_found) != 0);
608                 if (!found) {
609                         DEBUG(4, ("Printer %s not found\n", aprinter));
610                         TALLOC_FREE(tmp);
611                         return WERR_INVALID_PRINTER_NAME;
612                 }
613                 fstrcpy(sname, tmp);
614                 TALLOC_FREE(tmp);
615         }
616
617         /* Search all sharenames first as this is easier than pulling
618            the printer_info_2 off of disk. Don't use find_service() since
619            that calls out to map_username() */
620
621         /* do another loop to look for printernames */
622         for (snum = 0; !found && snum < n_services; snum++) {
623                 const char *printer = lp_const_servicename(snum);
624
625                 /* no point going on if this is not a printer */
626                 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
627                         continue;
628                 }
629
630                 /* ignore [printers] share */
631                 if (strequal(printer, "printers")) {
632                         continue;
633                 }
634
635                 fstrcpy(sname, printer);
636                 if (strequal(aprinter, printer)) {
637                         found = true;
638                         break;
639                 }
640
641                 /* no point looking up the printer object if
642                    we aren't allowing printername != sharename */
643                 if (lp_force_printername(snum)) {
644                         continue;
645                 }
646
647                 result = winreg_get_printer_internal(mem_ctx,
648                                             session_info,
649                                             msg_ctx,
650                                             sname,
651                                             &info2);
652                 if ( !W_ERROR_IS_OK(result) ) {
653                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
654                                  sname, win_errstr(result)));
655                         continue;
656                 }
657
658                 printername = strrchr(info2->printername, '\\');
659                 if (printername == NULL) {
660                         printername = info2->printername;
661                 } else {
662                         printername++;
663                 }
664
665                 if (strequal(printername, aprinter)) {
666                         found = true;
667                         break;
668                 }
669
670                 DEBUGADD(10, ("printername: %s\n", printername));
671
672                 TALLOC_FREE(info2);
673         }
674
675         if (!found) {
676                 gencache_set(cache_key, printer_not_found,
677                              time(NULL) + 300);
678                 TALLOC_FREE(cache_key);
679                 DEBUGADD(4,("Printer not found\n"));
680                 return WERR_INVALID_PRINTER_NAME;
681         }
682
683         gencache_set(cache_key, sname, time(NULL) + 300);
684         TALLOC_FREE(cache_key);
685
686         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
687
688         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
689
690         return WERR_OK;
691 }
692
693 /****************************************************************************
694  Find first available printer slot. creates a printer handle for you.
695  ****************************************************************************/
696
697 static WERROR open_printer_hnd(struct pipes_struct *p,
698                                struct policy_handle *hnd,
699                                const char *name,
700                                uint32_t access_granted)
701 {
702         struct printer_handle *new_printer;
703         WERROR result;
704
705         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
706
707         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
708         if (new_printer == NULL) {
709                 return WERR_NOT_ENOUGH_MEMORY;
710         }
711         talloc_set_destructor(new_printer, printer_entry_destructor);
712
713         /* This also steals the printer_handle on the policy_handle */
714         if (!create_policy_hnd(p, hnd, new_printer)) {
715                 TALLOC_FREE(new_printer);
716                 return WERR_INVALID_HANDLE;
717         }
718
719         /* Add to the internal list. */
720         DLIST_ADD(printers_list, new_printer);
721
722         new_printer->notify.option=NULL;
723
724         if (!set_printer_hnd_printertype(new_printer, name)) {
725                 close_printer_handle(p, hnd);
726                 return WERR_INVALID_HANDLE;
727         }
728
729         result = set_printer_hnd_name(p->mem_ctx,
730                                       get_session_info_system(),
731                                       p->msg_ctx,
732                                       new_printer, name);
733         if (!W_ERROR_IS_OK(result)) {
734                 close_printer_handle(p, hnd);
735                 return result;
736         }
737
738         new_printer->access_granted = access_granted;
739
740         DEBUG(5, ("%d printer handles active\n",
741                   (int)num_pipe_handles(p)));
742
743         return WERR_OK;
744 }
745
746 /***************************************************************************
747  check to see if the client motify handle is monitoring the notification
748  given by (notify_type, notify_field).
749  **************************************************************************/
750
751 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
752                                       uint16_t notify_field)
753 {
754         return true;
755 }
756
757 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
758                                 uint16_t notify_field)
759 {
760         struct spoolss_NotifyOption *option = p->notify.option;
761         uint32_t i, j;
762
763         /*
764          * Flags should always be zero when the change notify
765          * is registered by the client's spooler.  A user Win32 app
766          * might use the flags though instead of the NOTIFY_OPTION_INFO
767          * --jerry
768          */
769
770         if (!option) {
771                 return false;
772         }
773
774         if (p->notify.flags)
775                 return is_monitoring_event_flags(
776                         p->notify.flags, notify_type, notify_field);
777
778         for (i = 0; i < option->count; i++) {
779
780                 /* Check match for notify_type */
781
782                 if (option->types[i].type != notify_type)
783                         continue;
784
785                 /* Check match for field */
786
787                 for (j = 0; j < option->types[i].count; j++) {
788                         if (option->types[i].fields[j].field == notify_field) {
789                                 return true;
790                         }
791                 }
792         }
793
794         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
795                    p->servername, p->sharename, notify_type, notify_field));
796
797         return false;
798 }
799
800 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
801         _data->data.integer[0] = _integer; \
802         _data->data.integer[1] = 0;
803
804
805 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
806         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
807         if (!_data->data.string.string) {\
808                 _data->data.string.size = 0; \
809         } \
810         _data->data.string.size = strlen_m_term(_p) * 2;
811
812 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
813         _data->data.devmode.devmode = _devmode;
814
815 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
816                                    struct tm *t,
817                                    const char **pp,
818                                    uint32_t *plen)
819 {
820         struct spoolss_Time st;
821         uint32_t len = 16;
822         char *p;
823
824         if (!init_systemtime(&st, t)) {
825                 return;
826         }
827
828         p = talloc_array(mem_ctx, char, len);
829         if (!p) {
830                 return;
831         }
832
833         /*
834          * Systemtime must be linearized as a set of UINT16's.
835          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
836          */
837
838         SSVAL(p, 0, st.year);
839         SSVAL(p, 2, st.month);
840         SSVAL(p, 4, st.day_of_week);
841         SSVAL(p, 6, st.day);
842         SSVAL(p, 8, st.hour);
843         SSVAL(p, 10, st.minute);
844         SSVAL(p, 12, st.second);
845         SSVAL(p, 14, st.millisecond);
846
847         *pp = p;
848         *plen = len;
849 }
850
851 /* Convert a notification message to a struct spoolss_Notify */
852
853 static void notify_one_value(struct spoolss_notify_msg *msg,
854                              struct spoolss_Notify *data,
855                              TALLOC_CTX *mem_ctx)
856 {
857         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
858 }
859
860 static void notify_string(struct spoolss_notify_msg *msg,
861                           struct spoolss_Notify *data,
862                           TALLOC_CTX *mem_ctx)
863 {
864         /* The length of the message includes the trailing \0 */
865
866         data->data.string.size = msg->len * 2;
867         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
868         if (!data->data.string.string) {
869                 data->data.string.size = 0;
870                 return;
871         }
872 }
873
874 static void notify_system_time(struct spoolss_notify_msg *msg,
875                                struct spoolss_Notify *data,
876                                TALLOC_CTX *mem_ctx)
877 {
878         data->data.string.string = NULL;
879         data->data.string.size = 0;
880
881         if (msg->len != sizeof(time_t)) {
882                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
883                           msg->len));
884                 return;
885         }
886
887         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
888                                &data->data.string.string,
889                                &data->data.string.size);
890 }
891
892 struct notify2_message_table {
893         const char *name;
894         void (*fn)(struct spoolss_notify_msg *msg,
895                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
896 };
897
898 static struct notify2_message_table printer_notify_table[] = {
899         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
900         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
901         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
902         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
903         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
904         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
905         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
906         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
907         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
908         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
909         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
910         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
911         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
912         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
913         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
914         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
915         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
916         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
917         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
918 };
919
920 static struct notify2_message_table job_notify_table[] = {
921         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
922         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
923         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
924         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
925         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
926         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
927         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
928         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
929         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
930         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
931         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
932         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
933         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
934         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
935         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
936         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
937         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
938         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
939         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
940         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
941         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
942         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
943         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
944         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
945 };
946
947
948 /***********************************************************************
949  Allocate talloc context for container object
950  **********************************************************************/
951
952 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
953 {
954         if ( !ctr )
955                 return;
956
957         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
958
959         return;
960 }
961
962 /***********************************************************************
963  release all allocated memory and zero out structure
964  **********************************************************************/
965
966 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
967 {
968         if ( !ctr )
969                 return;
970
971         if ( ctr->ctx )
972                 talloc_destroy(ctr->ctx);
973
974         ZERO_STRUCTP(ctr);
975
976         return;
977 }
978
979 /***********************************************************************
980  **********************************************************************/
981
982 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
983 {
984         if ( !ctr )
985                 return NULL;
986
987         return ctr->ctx;
988 }
989
990 /***********************************************************************
991  **********************************************************************/
992
993 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
994 {
995         if ( !ctr || !ctr->msg_groups )
996                 return NULL;
997
998         if ( idx >= ctr->num_groups )
999                 return NULL;
1000
1001         return &ctr->msg_groups[idx];
1002
1003 }
1004
1005 /***********************************************************************
1006  How many groups of change messages do we have ?
1007  **********************************************************************/
1008
1009 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1010 {
1011         if ( !ctr )
1012                 return 0;
1013
1014         return ctr->num_groups;
1015 }
1016
1017 /***********************************************************************
1018  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1019  **********************************************************************/
1020
1021 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1022 {
1023         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1024         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1025         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1026         int                             i, new_slot;
1027
1028         if ( !ctr || !msg )
1029                 return 0;
1030
1031         /* loop over all groups looking for a matching printer name */
1032
1033         for ( i=0; i<ctr->num_groups; i++ ) {
1034                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1035                         break;
1036         }
1037
1038         /* add a new group? */
1039
1040         if ( i == ctr->num_groups ) {
1041                 ctr->num_groups++;
1042
1043                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1044                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1045                         return 0;
1046                 }
1047                 ctr->msg_groups = groups;
1048
1049                 /* clear the new entry and set the printer name */
1050
1051                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1052                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1053         }
1054
1055         /* add the change messages; 'i' is the correct index now regardless */
1056
1057         msg_grp = &ctr->msg_groups[i];
1058
1059         msg_grp->num_msgs++;
1060
1061         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1062                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1063                 return 0;
1064         }
1065         msg_grp->msgs = msg_list;
1066
1067         new_slot = msg_grp->num_msgs-1;
1068         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1069
1070         /* need to allocate own copy of data */
1071
1072         if ( msg->len != 0 )
1073                 msg_grp->msgs[new_slot].notify.data = (char *)
1074                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1075
1076         return ctr->num_groups;
1077 }
1078
1079 static void construct_info_data(struct spoolss_Notify *info_data,
1080                                 enum spoolss_NotifyType type,
1081                                 uint16_t field, int id);
1082
1083 /***********************************************************************
1084  Send a change notication message on all handles which have a call
1085  back registered
1086  **********************************************************************/
1087
1088 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1089                                   struct printer_handle *prn_hnd,
1090                                   SPOOLSS_NOTIFY_MSG *messages,
1091                                   uint32_t num_msgs,
1092                                   struct spoolss_Notify **_notifies,
1093                                   size_t *_count)
1094 {
1095         struct spoolss_Notify *notifies;
1096         SPOOLSS_NOTIFY_MSG *msg;
1097         size_t count = 0;
1098         uint32_t id;
1099         uint32_t i;
1100
1101         notifies = talloc_zero_array(mem_ctx,
1102                                      struct spoolss_Notify, num_msgs);
1103         if (!notifies) {
1104                 return ENOMEM;
1105         }
1106
1107         for (i = 0; i < num_msgs; i++) {
1108
1109                 msg = &messages[i];
1110
1111                 /* Are we monitoring this event? */
1112
1113                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1114                         continue;
1115                 }
1116
1117                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1118                            "for printer [%s]\n",
1119                            msg->type, msg->field, prn_hnd->sharename));
1120
1121                 /*
1122                  * if the is a printer notification handle and not a job
1123                  * notification type, then set the id to 0.
1124                  * Otherwise just use what was specified in the message.
1125                  *
1126                  * When registering change notification on a print server
1127                  * handle we always need to send back the id (snum) matching
1128                  * the printer for which the change took place.
1129                  * For change notify registered on a printer handle,
1130                  * this does not matter and the id should be 0.
1131                  *
1132                  * --jerry
1133                  */
1134
1135                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1136                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1137                         id = 0;
1138                 } else {
1139                         id = msg->id;
1140                 }
1141
1142                 /* Convert unix jobid to smb jobid */
1143
1144                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1145                         id = sysjob_to_jobid(msg->id);
1146
1147                         if (id == -1) {
1148                                 DEBUG(3, ("no such unix jobid %d\n",
1149                                           msg->id));
1150                                 continue;
1151                         }
1152                 }
1153
1154                 construct_info_data(&notifies[count],
1155                                     msg->type, msg->field, id);
1156
1157                 switch(msg->type) {
1158                 case PRINTER_NOTIFY_TYPE:
1159                         if (printer_notify_table[msg->field].fn) {
1160                                 printer_notify_table[msg->field].fn(msg,
1161                                                 &notifies[count], mem_ctx);
1162                         }
1163                         break;
1164
1165                 case JOB_NOTIFY_TYPE:
1166                         if (job_notify_table[msg->field].fn) {
1167                                 job_notify_table[msg->field].fn(msg,
1168                                                 &notifies[count], mem_ctx);
1169                         }
1170                         break;
1171
1172                 default:
1173                         DEBUG(5, ("Unknown notification type %d\n",
1174                                   msg->type));
1175                         continue;
1176                 }
1177
1178                 count++;
1179         }
1180
1181         *_notifies = notifies;
1182         *_count = count;
1183
1184         return 0;
1185 }
1186
1187 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1188                                 struct printer_handle *prn_hnd,
1189                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1190 {
1191         struct spoolss_Notify *notifies;
1192         size_t count = 0;
1193         union spoolss_ReplyPrinterInfo info;
1194         struct spoolss_NotifyInfo info0;
1195         uint32_t reply_result;
1196         NTSTATUS status;
1197         WERROR werr;
1198         int ret;
1199
1200         /* Is there notification on this handle? */
1201         if (prn_hnd->notify.cli_chan == NULL ||
1202             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1203             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1204             prn_hnd->notify.cli_chan->active_connections == 0) {
1205                 return 0;
1206         }
1207
1208         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1209                    prn_hnd->servername, prn_hnd->sharename));
1210
1211         /* For this printer? Print servers always receive notifications. */
1212         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1213             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1214                 return 0;
1215         }
1216
1217         DEBUG(10,("Our printer\n"));
1218
1219         /* build the array of change notifications */
1220         ret = build_notify2_messages(mem_ctx, prn_hnd,
1221                                      msg_group->msgs,
1222                                      msg_group->num_msgs,
1223                                      &notifies, &count);
1224         if (ret) {
1225                 return ret;
1226         }
1227
1228         info0.version   = 0x2;
1229         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1230         info0.count     = count;
1231         info0.notifies  = notifies;
1232
1233         info.info0 = &info0;
1234
1235         status = dcerpc_spoolss_RouterReplyPrinterEx(
1236                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1237                                 mem_ctx,
1238                                 &prn_hnd->notify.cli_hnd,
1239                                 prn_hnd->notify.change, /* color */
1240                                 prn_hnd->notify.flags,
1241                                 &reply_result,
1242                                 0, /* reply_type, must be 0 */
1243                                 info, &werr);
1244         if (!NT_STATUS_IS_OK(status)) {
1245                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1246                           "failed: %s\n",
1247                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1248                           nt_errstr(status)));
1249                 werr = ntstatus_to_werror(status);
1250         } else if (!W_ERROR_IS_OK(werr)) {
1251                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1252                           "failed: %s\n",
1253                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1254                           win_errstr(werr)));
1255         }
1256         switch (reply_result) {
1257         case 0:
1258                 break;
1259         case PRINTER_NOTIFY_INFO_DISCARDED:
1260         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1261         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1262                 break;
1263         default:
1264                 break;
1265         }
1266
1267         return 0;
1268 }
1269
1270 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1271 {
1272         struct printer_handle    *p;
1273         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1274         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1275         int ret;
1276
1277         if ( !msg_group ) {
1278                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1279                 return;
1280         }
1281
1282         if (!msg_group->msgs) {
1283                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1284                 return;
1285         }
1286
1287         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1288
1289         /* loop over all printers */
1290
1291         for (p = printers_list; p; p = p->next) {
1292                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1293                 if (ret) {
1294                         goto done;
1295                 }
1296         }
1297
1298 done:
1299         DEBUG(8,("send_notify2_changes: Exit...\n"));
1300         return;
1301 }
1302
1303 /***********************************************************************
1304  **********************************************************************/
1305
1306 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1307 {
1308
1309         uint32_t tv_sec, tv_usec;
1310         size_t offset = 0;
1311
1312         /* Unpack message */
1313
1314         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1315                              msg->printer);
1316
1317         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1318                                 &tv_sec, &tv_usec,
1319                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1320
1321         if (msg->len == 0)
1322                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1323                            &msg->notify.value[0], &msg->notify.value[1]);
1324         else
1325                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1326                            &msg->len, &msg->notify.data);
1327
1328         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1329                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1330
1331         tv->tv_sec = tv_sec;
1332         tv->tv_usec = tv_usec;
1333
1334         if (msg->len == 0)
1335                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1336                           msg->notify.value[1]));
1337         else
1338                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1339
1340         return true;
1341 }
1342
1343 /********************************************************************
1344  Receive a notify2 message list
1345  ********************************************************************/
1346
1347 static void receive_notify2_message_list(struct messaging_context *msg,
1348                                          void *private_data,
1349                                          uint32_t msg_type,
1350                                          struct server_id server_id,
1351                                          DATA_BLOB *data)
1352 {
1353         size_t                  msg_count, i;
1354         char                    *buf = (char *)data->data;
1355         char                    *msg_ptr;
1356         size_t                  msg_len;
1357         SPOOLSS_NOTIFY_MSG      notify;
1358         SPOOLSS_NOTIFY_MSG_CTR  messages;
1359         int                     num_groups;
1360
1361         if (data->length < 4) {
1362                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1363                 return;
1364         }
1365
1366         msg_count = IVAL(buf, 0);
1367         msg_ptr = buf + 4;
1368
1369         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1370
1371         if (msg_count == 0) {
1372                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1373                 return;
1374         }
1375
1376         /* initialize the container */
1377
1378         ZERO_STRUCT( messages );
1379         notify_msg_ctr_init( &messages );
1380
1381         /*
1382          * build message groups for each printer identified
1383          * in a change_notify msg.  Remember that a PCN message
1384          * includes the handle returned for the srv_spoolss_replyopenprinter()
1385          * call.  Therefore messages are grouped according to printer handle.
1386          */
1387
1388         for ( i=0; i<msg_count; i++ ) {
1389                 struct timeval msg_tv;
1390
1391                 if (msg_ptr + 4 - buf > data->length) {
1392                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1393                         return;
1394                 }
1395
1396                 msg_len = IVAL(msg_ptr,0);
1397                 msg_ptr += 4;
1398
1399                 if (msg_ptr + msg_len - buf > data->length) {
1400                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1401                         return;
1402                 }
1403
1404                 /* unpack messages */
1405
1406                 ZERO_STRUCT( notify );
1407                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1408                 msg_ptr += msg_len;
1409
1410                 /* add to correct list in container */
1411
1412                 notify_msg_ctr_addmsg( &messages, &notify );
1413
1414                 /* free memory that might have been allocated by notify2_unpack_msg() */
1415
1416                 if ( notify.len != 0 )
1417                         SAFE_FREE( notify.notify.data );
1418         }
1419
1420         /* process each group of messages */
1421
1422         num_groups = notify_msg_ctr_numgroups( &messages );
1423         for ( i=0; i<num_groups; i++ )
1424                 send_notify2_changes( &messages, i );
1425
1426
1427         /* cleanup */
1428
1429         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1430                 (uint32_t)msg_count ));
1431
1432         notify_msg_ctr_destroy( &messages );
1433
1434         return;
1435 }
1436
1437 /********************************************************************
1438  Send a message to ourself about new driver being installed
1439  so we can upgrade the information for each printer bound to this
1440  driver
1441  ********************************************************************/
1442
1443 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1444                                             struct messaging_context *msg_ctx)
1445 {
1446         int len = strlen(drivername);
1447
1448         if (!len)
1449                 return false;
1450
1451         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1452                 drivername));
1453
1454         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1455                            MSG_PRINTER_DRVUPGRADE,
1456                            (const uint8_t *)drivername, len+1);
1457
1458         return true;
1459 }
1460
1461 void srv_spoolss_cleanup(void)
1462 {
1463         struct printer_session_counter *session_counter;
1464
1465         for (session_counter = counter_list;
1466              session_counter != NULL;
1467              session_counter = counter_list) {
1468                 DLIST_REMOVE(counter_list, session_counter);
1469                 TALLOC_FREE(session_counter);
1470         }
1471 }
1472
1473 /**********************************************************************
1474  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1475  over all printers, upgrading ones as necessary
1476  This is now *ONLY* called inside the background lpq updater. JRA.
1477  **********************************************************************/
1478
1479 void do_drv_upgrade_printer(struct messaging_context *msg,
1480                             void *private_data,
1481                             uint32_t msg_type,
1482                             struct server_id server_id,
1483                             DATA_BLOB *data)
1484 {
1485         TALLOC_CTX *tmp_ctx;
1486         const struct auth_session_info *session_info = get_session_info_system();
1487         struct spoolss_PrinterInfo2 *pinfo2;
1488         WERROR result;
1489         const char *drivername;
1490         int snum;
1491         int n_services = lp_numservices();
1492         struct dcerpc_binding_handle *b = NULL;
1493
1494         tmp_ctx = talloc_new(NULL);
1495         if (!tmp_ctx) return;
1496
1497         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1498         if (!drivername) {
1499                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1500                 goto done;
1501         }
1502
1503         DEBUG(10, ("do_drv_upgrade_printer: "
1504                    "Got message for new driver [%s]\n", drivername));
1505
1506         /* Iterate the printer list */
1507
1508         for (snum = 0; snum < n_services; snum++) {
1509                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1510                         continue;
1511                 }
1512
1513                 /* ignore [printers] share */
1514                 if (strequal(lp_const_servicename(snum), "printers")) {
1515                         continue;
1516                 }
1517
1518                 if (b == NULL) {
1519                         result = winreg_printer_binding_handle(tmp_ctx,
1520                                                                session_info,
1521                                                                msg,
1522                                                                &b);
1523                         if (!W_ERROR_IS_OK(result)) {
1524                                 break;
1525                         }
1526                 }
1527
1528                 result = winreg_get_printer(tmp_ctx, b,
1529                                             lp_const_servicename(snum),
1530                                             &pinfo2);
1531
1532                 if (!W_ERROR_IS_OK(result)) {
1533                         continue;
1534                 }
1535
1536                 if (!pinfo2->drivername) {
1537                         continue;
1538                 }
1539
1540                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1541                         continue;
1542                 }
1543
1544                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1545
1546                 /* all we care about currently is the change_id */
1547                 result = winreg_printer_update_changeid(tmp_ctx, b,
1548                                                         pinfo2->printername);
1549
1550                 if (!W_ERROR_IS_OK(result)) {
1551                         DEBUG(3, ("do_drv_upgrade_printer: "
1552                                   "Failed to update changeid [%s]\n",
1553                                   win_errstr(result)));
1554                 }
1555         }
1556
1557         /* all done */
1558 done:
1559         talloc_free(tmp_ctx);
1560 }
1561
1562 /********************************************************************
1563  Update the cache for all printq's with a registered client
1564  connection
1565  ********************************************************************/
1566
1567 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1568 {
1569         struct printer_handle *printer = printers_list;
1570         int snum;
1571
1572         /* loop through all printers and update the cache where
1573            a client is connected */
1574         while (printer) {
1575                 if ((printer->printer_type == SPLHND_PRINTER) &&
1576                     ((printer->notify.cli_chan != NULL) &&
1577                      (printer->notify.cli_chan->active_connections > 0))) {
1578                         snum = print_queue_snum(printer->sharename);
1579                         print_queue_status(msg_ctx, snum, NULL, NULL);
1580                 }
1581
1582                 printer = printer->next;
1583         }
1584
1585         return;
1586 }
1587
1588 /****************************************************************
1589  _spoolss_OpenPrinter
1590 ****************************************************************/
1591
1592 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1593                             struct spoolss_OpenPrinter *r)
1594 {
1595         struct spoolss_OpenPrinterEx e;
1596         struct spoolss_UserLevel1 level1;
1597         WERROR werr;
1598
1599         ZERO_STRUCT(level1);
1600
1601         e.in.printername        = r->in.printername;
1602         e.in.datatype           = r->in.datatype;
1603         e.in.devmode_ctr        = r->in.devmode_ctr;
1604         e.in.access_mask        = r->in.access_mask;
1605         e.in.userlevel_ctr.level                = 1;
1606         e.in.userlevel_ctr.user_info.level1     = &level1;
1607
1608         e.out.handle            = r->out.handle;
1609
1610         werr = _spoolss_OpenPrinterEx(p, &e);
1611
1612         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1613                 /* OpenPrinterEx returns this for a bad
1614                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1615                  * instead.
1616                  */
1617                 werr = WERR_INVALID_PRINTER_NAME;
1618         }
1619
1620         return werr;
1621 }
1622
1623 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1624                               struct spoolss_DeviceMode *orig,
1625                               struct spoolss_DeviceMode **dest)
1626 {
1627         struct spoolss_DeviceMode *dm;
1628
1629         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1630         if (!dm) {
1631                 return WERR_NOT_ENOUGH_MEMORY;
1632         }
1633
1634         /* copy all values, then duplicate strings and structs */
1635         *dm = *orig;
1636
1637         dm->devicename = talloc_strdup(dm, orig->devicename);
1638         if (!dm->devicename) {
1639                 return WERR_NOT_ENOUGH_MEMORY;
1640         }
1641         dm->formname = talloc_strdup(dm, orig->formname);
1642         if (!dm->formname) {
1643                 return WERR_NOT_ENOUGH_MEMORY;
1644         }
1645         if (orig->driverextra_data.data) {
1646                 dm->driverextra_data.data =
1647                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1648                                         orig->driverextra_data.length);
1649                 if (!dm->driverextra_data.data) {
1650                         return WERR_NOT_ENOUGH_MEMORY;
1651                 }
1652         }
1653
1654         *dest = dm;
1655         return WERR_OK;
1656 }
1657
1658 /****************************************************************
1659  _spoolss_OpenPrinterEx
1660 ****************************************************************/
1661
1662 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1663                               struct spoolss_OpenPrinterEx *r)
1664 {
1665         int snum;
1666         char *raddr;
1667         char *rhost;
1668         struct printer_handle *Printer=NULL;
1669         WERROR result;
1670         int rc;
1671
1672         if (!r->in.printername) {
1673                 return WERR_INVALID_PARAMETER;
1674         }
1675
1676         if (!*r->in.printername) {
1677                 return WERR_INVALID_PARAMETER;
1678         }
1679
1680         if (r->in.userlevel_ctr.level > 3) {
1681                 return WERR_INVALID_PARAMETER;
1682         }
1683         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1684             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1685             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1686                 return WERR_INVALID_PARAMETER;
1687         }
1688
1689         /*
1690          * The printcap printer share inventory is updated on client
1691          * enumeration. For clients that do not perform enumeration prior to
1692          * access, such as cupssmbadd, we reinitialise the printer share
1693          * inventory on open as well.
1694          */
1695         become_root();
1696         delete_and_reload_printers(server_event_context(), p->msg_ctx);
1697         unbecome_root();
1698
1699         /* some sanity check because you can open a printer or a print server */
1700         /* aka: \\server\printer or \\server */
1701
1702         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1703
1704         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1705         if (!W_ERROR_IS_OK(result)) {
1706                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1707                         "for printer %s\n", r->in.printername));
1708                 ZERO_STRUCTP(r->out.handle);
1709                 return result;
1710         }
1711
1712         Printer = find_printer_index_by_hnd(p, r->out.handle);
1713         if ( !Printer ) {
1714                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1715                         "handle we created for printer %s\n", r->in.printername));
1716                 close_printer_handle(p, r->out.handle);
1717                 ZERO_STRUCTP(r->out.handle);
1718                 return WERR_INVALID_PARAMETER;
1719         }
1720
1721         /*
1722          * First case: the user is opening the print server:
1723          *
1724          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1725          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1726          *
1727          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1728          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1729          * or if the user is listed in the smb.conf printer admin parameter.
1730          *
1731          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1732          * client view printer folder, but does not show the MSAPW.
1733          *
1734          * Note: this test needs code to check access rights here too. Jeremy
1735          * could you look at this?
1736          *
1737          * Second case: the user is opening a printer:
1738          * NT doesn't let us connect to a printer if the connecting user
1739          * doesn't have print permission.
1740          *
1741          * Third case: user is opening a Port Monitor
1742          * access checks same as opening a handle to the print server.
1743          */
1744
1745         switch (Printer->printer_type )
1746         {
1747         case SPLHND_SERVER:
1748         case SPLHND_PORTMON_TCP:
1749         case SPLHND_PORTMON_LOCAL:
1750                 /* Printserver handles use global struct... */
1751
1752                 snum = -1;
1753
1754                 if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1755                         r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1756                         r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1757                 }
1758
1759                 /* Map standard access rights to object specific access rights */
1760
1761                 se_map_standard(&r->in.access_mask,
1762                                 &printserver_std_mapping);
1763
1764                 /* Deny any object specific bits that don't apply to print
1765                    servers (i.e printer and job specific bits) */
1766
1767                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1768
1769                 if (r->in.access_mask &
1770                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1771                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1772                         close_printer_handle(p, r->out.handle);
1773                         ZERO_STRUCTP(r->out.handle);
1774                         return WERR_ACCESS_DENIED;
1775                 }
1776
1777                 /* Allow admin access */
1778
1779                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1780                 {
1781                         if (!lp_show_add_printer_wizard()) {
1782                                 close_printer_handle(p, r->out.handle);
1783                                 ZERO_STRUCTP(r->out.handle);
1784                                 return WERR_ACCESS_DENIED;
1785                         }
1786
1787                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1788                            and not a printer admin, then fail */
1789
1790                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1791                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1792                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1793                                                 p->session_info->security_token)) {
1794                                 close_printer_handle(p, r->out.handle);
1795                                 ZERO_STRUCTP(r->out.handle);
1796                                 DEBUG(3,("access DENIED as user is not root, "
1797                                         "has no printoperator privilege and is "
1798                                         "not a member of the printoperator builtin group\n"));
1799                                 return WERR_ACCESS_DENIED;
1800                         }
1801
1802                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1803                 }
1804                 else
1805                 {
1806                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1807                 }
1808
1809                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1810                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1811
1812                 break;
1813
1814         case SPLHND_PRINTER:
1815                 /* NT doesn't let us connect to a printer if the connecting user
1816                    doesn't have print permission.  */
1817
1818                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1819                         close_printer_handle(p, r->out.handle);
1820                         ZERO_STRUCTP(r->out.handle);
1821                         return WERR_INVALID_HANDLE;
1822                 }
1823
1824                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1825                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1826                 }
1827
1828                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1829
1830                 /* map an empty access mask to the minimum access mask */
1831                 if (r->in.access_mask == 0x0)
1832                         r->in.access_mask = PRINTER_ACCESS_USE;
1833
1834                 /*
1835                  * If we are not serving the printer driver for this printer,
1836                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1837                  * will keep NT clients happy  --jerry
1838                  */
1839
1840                 if (lp_use_client_driver(snum)
1841                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1842                 {
1843                         r->in.access_mask = PRINTER_ACCESS_USE;
1844                 }
1845
1846                 /* check smb.conf parameters and the the sec_desc */
1847                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1848                                                          p->mem_ctx);
1849                 if (raddr == NULL) {
1850                         return WERR_NOT_ENOUGH_MEMORY;
1851                 }
1852
1853                 rc = get_remote_hostname(p->remote_address,
1854                                          &rhost,
1855                                          p->mem_ctx);
1856                 if (rc < 0) {
1857                         return WERR_NOT_ENOUGH_MEMORY;
1858                 }
1859                 if (strequal(rhost, "UNKNOWN")) {
1860                         rhost = raddr;
1861                 }
1862
1863                 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1864                                   rhost, raddr)) {
1865                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1866                         ZERO_STRUCTP(r->out.handle);
1867                         return WERR_ACCESS_DENIED;
1868                 }
1869
1870                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1871                                    p->session_info->security_token, snum) ||
1872                     !W_ERROR_IS_OK(print_access_check(p->session_info,
1873                                                       p->msg_ctx,
1874                                                       snum,
1875                                                       r->in.access_mask))) {
1876                         DEBUG(3, ("access DENIED for printer open\n"));
1877                         close_printer_handle(p, r->out.handle);
1878                         ZERO_STRUCTP(r->out.handle);
1879                         return WERR_ACCESS_DENIED;
1880                 }
1881
1882                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1883                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1884                         close_printer_handle(p, r->out.handle);
1885                         ZERO_STRUCTP(r->out.handle);
1886                         return WERR_ACCESS_DENIED;
1887                 }
1888
1889                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1890                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1891                 else
1892                         r->in.access_mask = PRINTER_ACCESS_USE;
1893
1894                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1895                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1896
1897                 winreg_create_printer_internal(p->mem_ctx,
1898                                       get_session_info_system(),
1899                                       p->msg_ctx,
1900                                       lp_const_servicename(snum));
1901
1902                 break;
1903
1904         default:
1905                 /* sanity check to prevent programmer error */
1906                 ZERO_STRUCTP(r->out.handle);
1907                 return WERR_INVALID_HANDLE;
1908         }
1909
1910         Printer->access_granted = r->in.access_mask;
1911
1912         /*
1913          * If the client sent a devmode in the OpenPrinter() call, then
1914          * save it here in case we get a job submission on this handle
1915          */
1916
1917          if ((Printer->printer_type != SPLHND_SERVER)
1918           && (r->in.devmode_ctr.devmode != NULL)) {
1919                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1920                                 &Printer->devmode);
1921          }
1922
1923         return WERR_OK;
1924 }
1925
1926 /****************************************************************
1927  _spoolss_ClosePrinter
1928 ****************************************************************/
1929
1930 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1931                              struct spoolss_ClosePrinter *r)
1932 {
1933         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1934
1935         if (Printer && Printer->document_started) {
1936                 struct spoolss_EndDocPrinter e;
1937
1938                 e.in.handle = r->in.handle;
1939
1940                 _spoolss_EndDocPrinter(p, &e);
1941         }
1942
1943         if (!close_printer_handle(p, r->in.handle))
1944                 return WERR_INVALID_HANDLE;
1945
1946         /* clear the returned printer handle.  Observed behavior
1947            from Win2k server.  Don't think this really matters.
1948            Previous code just copied the value of the closed
1949            handle.    --jerry */
1950
1951         ZERO_STRUCTP(r->out.handle);
1952
1953         return WERR_OK;
1954 }
1955
1956 /****************************************************************
1957  _spoolss_DeletePrinter
1958 ****************************************************************/
1959
1960 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1961                               struct spoolss_DeletePrinter *r)
1962 {
1963         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1964         WERROR result;
1965         int snum;
1966
1967         if (Printer && Printer->document_started) {
1968                 struct spoolss_EndDocPrinter e;
1969
1970                 e.in.handle = r->in.handle;
1971
1972                 _spoolss_EndDocPrinter(p, &e);
1973         }
1974
1975         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1976                 winreg_delete_printer_key_internal(p->mem_ctx,
1977                                           get_session_info_system(),
1978                                           p->msg_ctx,
1979                                           lp_const_servicename(snum),
1980                                           "");
1981         }
1982
1983         result = delete_printer_handle(p, r->in.handle);
1984
1985         return result;
1986 }
1987
1988 /*******************************************************************
1989  * static function to lookup the version id corresponding to an
1990  * long architecture string
1991  ******************************************************************/
1992
1993 static const struct print_architecture_table_node archi_table[]= {
1994
1995         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1996         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1997         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1998         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1999         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2000         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2001         {"Windows x64",          SPL_ARCH_X64,          3 },
2002         {NULL,                   "",            -1 }
2003 };
2004
2005 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2006                                    SPOOLSS_DRIVER_VERSION_NT35,
2007                                    SPOOLSS_DRIVER_VERSION_NT4,
2008                                    SPOOLSS_DRIVER_VERSION_200X,
2009                                    -1};
2010
2011 static int get_version_id(const char *arch)
2012 {
2013         int i;
2014
2015         for (i=0; archi_table[i].long_archi != NULL; i++)
2016         {
2017                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2018                         return (archi_table[i].version);
2019         }
2020
2021         return -1;
2022 }
2023
2024 /****************************************************************
2025  _spoolss_DeletePrinterDriver
2026 ****************************************************************/
2027
2028 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2029                                     struct spoolss_DeletePrinterDriver *r)
2030 {
2031
2032         struct spoolss_DriverInfo8 *info = NULL;
2033         int                             version;
2034         WERROR                          status;
2035         struct dcerpc_binding_handle *b;
2036         TALLOC_CTX *tmp_ctx = NULL;
2037         int i;
2038         bool found;
2039
2040         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2041            and not a printer admin, then fail */
2042
2043         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2044             !security_token_has_privilege(p->session_info->security_token,
2045                                           SEC_PRIV_PRINT_OPERATOR)) {
2046                 return WERR_ACCESS_DENIED;
2047         }
2048
2049         if (r->in.architecture == NULL || r->in.driver == NULL) {
2050                 return WERR_INVALID_ENVIRONMENT;
2051         }
2052
2053         /* check that we have a valid driver name first */
2054
2055         if ((version = get_version_id(r->in.architecture)) == -1) {
2056                 return WERR_INVALID_ENVIRONMENT;
2057         }
2058
2059         tmp_ctx = talloc_new(p->mem_ctx);
2060         if (!tmp_ctx) {
2061                 return WERR_NOT_ENOUGH_MEMORY;
2062         }
2063
2064         status = winreg_printer_binding_handle(tmp_ctx,
2065                                                get_session_info_system(),
2066                                                p->msg_ctx,
2067                                                &b);
2068         if (!W_ERROR_IS_OK(status)) {
2069                 goto done;
2070         }
2071
2072         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2073                 status = winreg_get_driver(tmp_ctx, b,
2074                                            r->in.architecture, r->in.driver,
2075                                            drv_cversion[i], &info);
2076                 if (!W_ERROR_IS_OK(status)) {
2077                         DEBUG(5, ("skipping del of driver with version %d\n",
2078                                   drv_cversion[i]));
2079                         continue;
2080                 }
2081                 found = true;
2082
2083                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2084                         status = WERR_PRINTER_DRIVER_IN_USE;
2085                         goto done;
2086                 }
2087
2088                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2089                 if (!W_ERROR_IS_OK(status)) {
2090                         DEBUG(0, ("failed del of driver with version %d\n",
2091                                   drv_cversion[i]));
2092                         goto done;
2093                 }
2094         }
2095         if (found == false) {
2096                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2097                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2098         } else {
2099                 status = WERR_OK;
2100         }
2101
2102 done:
2103         talloc_free(tmp_ctx);
2104
2105         return status;
2106 }
2107
2108 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2109                                   struct pipes_struct *p,
2110                                   struct spoolss_DeletePrinterDriverEx *r,
2111                                   struct dcerpc_binding_handle *b,
2112                                   struct spoolss_DriverInfo8 *info)
2113 {
2114         WERROR status;
2115         bool delete_files;
2116
2117         if (printer_driver_in_use(mem_ctx, b, info)) {
2118                 status = WERR_PRINTER_DRIVER_IN_USE;
2119                 goto done;
2120         }
2121
2122         /*
2123          * we have a couple of cases to consider.
2124          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2125          *     then the delete should fail if **any** files overlap with
2126          *     other drivers
2127          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2128          *     non-overlapping files
2129          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2130          *     are set, then do not delete any files
2131          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2132          */
2133
2134         delete_files = r->in.delete_flags
2135                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2136
2137
2138         if (delete_files) {
2139                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2140                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2141                         status = WERR_PRINTER_DRIVER_IN_USE;
2142                         goto done;
2143                 }
2144                 /*
2145                  * printer_driver_files_in_use() has trimmed overlapping files
2146                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2147                  */
2148         }
2149
2150
2151         status = winreg_del_driver(mem_ctx, b, info, info->version);
2152         if (!W_ERROR_IS_OK(status)) {
2153                 goto done;
2154         }
2155
2156         /*
2157          * now delete any associated files if delete_files is
2158          * true. Even if this part failes, we return succes
2159          * because the driver doesn not exist any more
2160          */
2161         if (delete_files) {
2162                 delete_driver_files(p->session_info, info);
2163         }
2164
2165 done:
2166         return status;
2167 }
2168
2169 /****************************************************************
2170  _spoolss_DeletePrinterDriverEx
2171 ****************************************************************/
2172
2173 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2174                                       struct spoolss_DeletePrinterDriverEx *r)
2175 {
2176         struct spoolss_DriverInfo8 *info = NULL;
2177         WERROR                          status;
2178         struct dcerpc_binding_handle *b;
2179         TALLOC_CTX *tmp_ctx = NULL;
2180         int i;
2181         bool found;
2182
2183         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2184            and not a printer admin, then fail */
2185
2186         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2187             !security_token_has_privilege(p->session_info->security_token,
2188                                           SEC_PRIV_PRINT_OPERATOR)) {
2189                 return WERR_ACCESS_DENIED;
2190         }
2191
2192         if (r->in.architecture == NULL || r->in.driver == NULL) {
2193                 return WERR_INVALID_ENVIRONMENT;
2194         }
2195
2196         /* check that we have a valid driver name first */
2197         if (get_version_id(r->in.architecture) == -1) {
2198                 /* this is what NT returns */
2199                 return WERR_INVALID_ENVIRONMENT;
2200         }
2201
2202         tmp_ctx = talloc_new(p->mem_ctx);
2203         if (!tmp_ctx) {
2204                 return WERR_NOT_ENOUGH_MEMORY;
2205         }
2206
2207         status = winreg_printer_binding_handle(tmp_ctx,
2208                                                get_session_info_system(),
2209                                                p->msg_ctx,
2210                                                &b);
2211         if (!W_ERROR_IS_OK(status)) {
2212                 goto done;
2213         }
2214
2215         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2216                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2217                  && (drv_cversion[i] != r->in.version)) {
2218                         continue;
2219                 }
2220
2221                 /* check if a driver with this version exists before delete */
2222                 status = winreg_get_driver(tmp_ctx, b,
2223                                            r->in.architecture, r->in.driver,
2224                                            drv_cversion[i], &info);
2225                 if (!W_ERROR_IS_OK(status)) {
2226                         DEBUG(5, ("skipping del of driver with version %d\n",
2227                                   drv_cversion[i]));
2228                         continue;
2229                 }
2230                 found = true;
2231
2232                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2233                 if (!W_ERROR_IS_OK(status)) {
2234                         DEBUG(0, ("failed to delete driver with version %d\n",
2235                                   drv_cversion[i]));
2236                         goto done;
2237                 }
2238         }
2239         if (found == false) {
2240                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2241                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2242         } else {
2243                 status = WERR_OK;
2244         }
2245
2246 done:
2247         talloc_free(tmp_ctx);
2248         return status;
2249 }
2250
2251
2252 /********************************************************************
2253  GetPrinterData on a printer server Handle.
2254 ********************************************************************/
2255
2256 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2257                                             const char *value,
2258                                             enum winreg_Type *type,
2259                                             union spoolss_PrinterData *data)
2260 {
2261         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2262
2263         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2264                 *type = REG_DWORD;
2265                 SIVAL(&data->value, 0, 0x00);
2266                 return WERR_OK;
2267         }
2268
2269         if (!strcasecmp_m(value, "BeepEnabled")) {
2270                 *type = REG_DWORD;
2271                 SIVAL(&data->value, 0, 0x00);
2272                 return WERR_OK;
2273         }
2274
2275         if (!strcasecmp_m(value, "EventLog")) {
2276                 *type = REG_DWORD;
2277                 /* formally was 0x1b */
2278                 SIVAL(&data->value, 0, 0x00);
2279                 return WERR_OK;
2280         }
2281
2282         if (!strcasecmp_m(value, "NetPopup")) {
2283                 *type = REG_DWORD;
2284                 SIVAL(&data->value, 0, 0x00);
2285                 return WERR_OK;
2286         }
2287
2288         if (!strcasecmp_m(value, "MajorVersion")) {
2289                 *type = REG_DWORD;
2290
2291                 /* Windows NT 4.0 seems to not allow uploading of drivers
2292                    to a server that reports 0x3 as the MajorVersion.
2293                    need to investigate more how Win2k gets around this .
2294                    -- jerry */
2295
2296                 if (RA_WINNT == get_remote_arch()) {
2297                         SIVAL(&data->value, 0, 0x02);
2298                 } else {
2299                         SIVAL(&data->value, 0, 0x03);
2300                 }
2301
2302                 return WERR_OK;
2303         }
2304
2305         if (!strcasecmp_m(value, "MinorVersion")) {
2306                 *type = REG_DWORD;
2307                 SIVAL(&data->value, 0, 0x00);
2308                 return WERR_OK;
2309         }
2310
2311         /* REG_BINARY
2312          *  uint32_t size        = 0x114
2313          *  uint32_t major       = 5
2314          *  uint32_t minor       = [0|1]
2315          *  uint32_t build       = [2195|2600]
2316          *  extra unicode string = e.g. "Service Pack 3"
2317          */
2318         if (!strcasecmp_m(value, "OSVersion")) {
2319                 DATA_BLOB blob;
2320                 enum ndr_err_code ndr_err;
2321                 struct spoolss_OSVersion os;
2322
2323                 /*
2324                  * Set the default OSVersion to:
2325                  *
2326                  *     Windows Server 2003R2 SP2 (5.2.3790)
2327                  *
2328                  * used to be Windows 2000 (5.0.2195)
2329                  */
2330                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
2331                                                       "spoolss", "os_major",
2332                                                       GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
2333                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
2334                                                       "spoolss", "os_minor",
2335                                                       GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
2336                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
2337                                                       "spoolss", "os_build",
2338                                                       GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
2339                 os.extra_string         = "";   /* leave extra string empty */
2340
2341                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2342                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2343                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2344                         return WERR_GEN_FAILURE;
2345                 }
2346
2347                 if (DEBUGLEVEL >= 10) {
2348                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2349                 }
2350
2351                 *type = REG_BINARY;
2352                 data->binary = blob;
2353
2354                 return WERR_OK;
2355         }
2356
2357
2358         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2359                 *type = REG_SZ;
2360
2361                 data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
2362                 W_ERROR_HAVE_NO_MEMORY(data->string);
2363
2364                 return WERR_OK;
2365         }
2366
2367         if (!strcasecmp_m(value, "Architecture")) {
2368                 *type = REG_SZ;
2369                 data->string = talloc_strdup(mem_ctx,
2370                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
2371                 W_ERROR_HAVE_NO_MEMORY(data->string);
2372
2373                 return WERR_OK;
2374         }
2375
2376         if (!strcasecmp_m(value, "DsPresent")) {
2377                 *type = REG_DWORD;
2378
2379                 /* only show the publish check box if we are a
2380                    member of a AD domain */
2381
2382                 if (lp_security() == SEC_ADS) {
2383                         SIVAL(&data->value, 0, 0x01);
2384                 } else {
2385                         SIVAL(&data->value, 0, 0x00);
2386                 }
2387                 return WERR_OK;
2388         }
2389
2390         if (!strcasecmp_m(value, "DNSMachineName")) {
2391                 const char *hostname = get_mydnsfullname();
2392
2393                 if (!hostname) {
2394                         return WERR_FILE_NOT_FOUND;
2395                 }
2396
2397                 *type = REG_SZ;
2398                 data->string = talloc_strdup(mem_ctx, hostname);
2399                 W_ERROR_HAVE_NO_MEMORY(data->string);
2400
2401                 return WERR_OK;
2402         }
2403
2404         *type = REG_NONE;
2405
2406         return WERR_INVALID_PARAMETER;
2407 }
2408
2409 /****************************************************************
2410  _spoolss_GetPrinterData
2411 ****************************************************************/
2412
2413 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2414                                struct spoolss_GetPrinterData *r)
2415 {
2416         struct spoolss_GetPrinterDataEx r2;
2417
2418         r2.in.handle            = r->in.handle;
2419         r2.in.key_name          = "PrinterDriverData";
2420         r2.in.value_name        = r->in.value_name;
2421         r2.in.offered           = r->in.offered;
2422         r2.out.type             = r->out.type;
2423         r2.out.data             = r->out.data;
2424         r2.out.needed           = r->out.needed;
2425
2426         return _spoolss_GetPrinterDataEx(p, &r2);
2427 }
2428
2429 /*********************************************************
2430  Connect to the client machine.
2431 **********************************************************/
2432
2433 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2434                                       struct sockaddr_storage *client_ss, const char *remote_machine)
2435 {
2436         NTSTATUS ret;
2437         struct sockaddr_storage rm_addr;
2438         char addr[INET6_ADDRSTRLEN];
2439
2440         if ( is_zero_addr(client_ss) ) {
2441                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2442                         remote_machine));
2443                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2444                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2445                         return false;
2446                 }
2447                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2448         } else {
2449                 rm_addr = *client_ss;
2450                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2451                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2452                         addr));
2453         }
2454
2455         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2456                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2457                         addr));
2458                 return false;
2459         }
2460
2461         /* setup the connection */
2462         ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2463                 &rm_addr, 0, "IPC$", "IPC",
2464                 "", /* username */
2465                 "", /* domain */
2466                 "", /* password */
2467                 0, lp_client_signing());
2468
2469         if ( !NT_STATUS_IS_OK( ret ) ) {
2470                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2471                         remote_machine ));
2472                 return false;
2473         }
2474
2475         if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
2476                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2477                 cli_shutdown(*pp_cli);
2478                 return false;
2479         }
2480
2481         /*
2482          * Ok - we have an anonymous connection to the IPC$ share.
2483          * Now start the NT Domain stuff :-).
2484          */
2485
2486         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2487         if (!NT_STATUS_IS_OK(ret)) {
2488                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2489                         remote_machine, nt_errstr(ret)));
2490                 cli_shutdown(*pp_cli);
2491                 return false;
2492         }
2493
2494         return true;
2495 }
2496
2497 /***************************************************************************
2498  Connect to the client.
2499 ****************************************************************************/
2500
2501 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2502                                         uint32_t localprinter,
2503                                         enum winreg_Type type,
2504                                         struct policy_handle *handle,
2505                                         struct notify_back_channel **_chan,
2506                                         struct sockaddr_storage *client_ss,
2507                                         struct messaging_context *msg_ctx)
2508 {
2509         WERROR result;
2510         NTSTATUS status;
2511         struct notify_back_channel *chan;
2512
2513         for (chan = back_channels; chan; chan = chan->next) {
2514                 if (memcmp(&chan->client_address, client_ss,
2515                            sizeof(struct sockaddr_storage)) == 0) {
2516                         break;
2517                 }
2518         }
2519
2520         /*
2521          * If it's the first connection, contact the client
2522          * and connect to the IPC$ share anonymously
2523          */
2524         if (!chan) {
2525                 fstring unix_printer;
2526
2527                 /* the +2 is to strip the leading 2 backslashs */
2528                 fstrcpy(unix_printer, printer + 2);
2529
2530                 chan = talloc_zero(NULL, struct notify_back_channel);
2531                 if (!chan) {
2532                         return false;
2533                 }
2534                 chan->client_address = *client_ss;
2535
2536                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2537                         TALLOC_FREE(chan);
2538                         return false;
2539                 }
2540
2541                 DLIST_ADD(back_channels, chan);
2542
2543                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2544                                    receive_notify2_message_list);
2545         }
2546
2547         if (chan->cli_pipe == NULL ||
2548             chan->cli_pipe->binding_handle == NULL) {
2549                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2550                         "NULL %s for printer %s\n",
2551                         chan->cli_pipe == NULL ?
2552                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2553                         printer));
2554                 return false;
2555         }
2556
2557         /*
2558          * Tell the specific printing tdb we want messages for this printer
2559          * by registering our PID.
2560          */
2561
2562         if (!print_notify_register_pid(snum)) {
2563                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2564                           printer));
2565         }
2566
2567         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2568                                                  talloc_tos(),
2569                                                  printer,
2570                                                  localprinter,
2571                                                  type,
2572                                                  0,
2573                                                  NULL,
2574                                                  handle,
2575                                                  &result);
2576         if (!NT_STATUS_IS_OK(status)) {
2577                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2578                 result = ntstatus_to_werror(status);
2579         } else if (!W_ERROR_IS_OK(result)) {
2580                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2581         }
2582
2583         chan->active_connections++;
2584         *_chan = chan;
2585
2586         return (W_ERROR_IS_OK(result));
2587 }
2588
2589 /****************************************************************
2590  ****************************************************************/
2591
2592 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2593                                                              const struct spoolss_NotifyOption *r)
2594 {
2595         struct spoolss_NotifyOption *option;
2596         uint32_t i,k;
2597
2598         if (!r) {
2599                 return NULL;
2600         }
2601
2602         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2603         if (!option) {
2604                 return NULL;
2605         }
2606
2607         *option = *r;
2608
2609         if (!option->count) {
2610                 return option;
2611         }
2612
2613         option->types = talloc_zero_array(option,
2614                 struct spoolss_NotifyOptionType, option->count);
2615         if (!option->types) {
2616                 talloc_free(option);
2617                 return NULL;
2618         }
2619
2620         for (i=0; i < option->count; i++) {
2621                 option->types[i] = r->types[i];
2622
2623                 if (option->types[i].count) {
2624                         option->types[i].fields = talloc_zero_array(option,
2625                                 union spoolss_Field, option->types[i].count);
2626                         if (!option->types[i].fields) {
2627                                 talloc_free(option);
2628                                 return NULL;
2629                         }
2630                         for (k=0; k<option->types[i].count; k++) {
2631                                 option->types[i].fields[k] =
2632                                         r->types[i].fields[k];
2633                         }
2634                 }
2635         }
2636
2637         return option;
2638 }
2639
2640 /****************************************************************
2641  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2642  *
2643  * before replying OK: status=0 a rpc call is made to the workstation
2644  * asking ReplyOpenPrinter
2645  *
2646  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2647  * called from api_spoolss_rffpcnex
2648 ****************************************************************/
2649
2650 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2651                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2652 {
2653         int snum = -1;
2654         struct spoolss_NotifyOption *option = r->in.notify_options;
2655         struct sockaddr_storage client_ss;
2656         ssize_t client_len;
2657
2658         /* store the notify value in the printer struct */
2659
2660         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2661
2662         if (!Printer) {
2663                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2664                         "Invalid handle (%s:%u:%u).\n",
2665                         OUR_HANDLE(r->in.handle)));
2666                 return WERR_INVALID_HANDLE;
2667         }
2668
2669         Printer->notify.flags           = r->in.flags;
2670         Printer->notify.options         = r->in.options;
2671         Printer->notify.printerlocal    = r->in.printer_local;
2672         Printer->notify.msg_ctx         = p->msg_ctx;
2673
2674         TALLOC_FREE(Printer->notify.option);
2675         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2676
2677         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2678
2679         /* Connect to the client machine and send a ReplyOpenPrinter */
2680
2681         if ( Printer->printer_type == SPLHND_SERVER)
2682                 snum = -1;
2683         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2684                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2685                 return WERR_INVALID_HANDLE;
2686
2687         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2688                   "remote_address is %s\n",
2689                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2690
2691         if (!lp_print_notify_backchannel(snum)) {
2692                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2693                         "backchannel disabled\n"));
2694                 return WERR_RPC_S_SERVER_UNAVAILABLE;
2695         }
2696
2697         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2698                                                   (struct sockaddr *) &client_ss,
2699                                                   sizeof(struct sockaddr_storage));
2700         if (client_len < 0) {
2701                 return WERR_NOT_ENOUGH_MEMORY;
2702         }
2703
2704         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2705                                         Printer->notify.printerlocal, REG_SZ,
2706                                         &Printer->notify.cli_hnd,
2707                                         &Printer->notify.cli_chan,
2708                                         &client_ss, p->msg_ctx)) {
2709                 return WERR_RPC_S_SERVER_UNAVAILABLE;
2710         }
2711
2712         return WERR_OK;
2713 }
2714
2715 /*******************************************************************
2716  * fill a notify_info_data with the servername
2717  ********************************************************************/
2718
2719 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2720                                        int snum,
2721                                        struct spoolss_Notify *data,
2722                                        print_queue_struct *queue,
2723                                        struct spoolss_PrinterInfo2 *pinfo2,
2724                                        TALLOC_CTX *mem_ctx)
2725 {
2726         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2727 }
2728
2729 /*******************************************************************
2730  * fill a notify_info_data with the printername (not including the servername).
2731  ********************************************************************/
2732
2733 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2734                                         int snum,
2735                                         struct spoolss_Notify *data,
2736                                         print_queue_struct *queue,
2737                                         struct spoolss_PrinterInfo2 *pinfo2,
2738                                         TALLOC_CTX *mem_ctx)
2739 {
2740         /* the notify name should not contain the \\server\ part */
2741         const char *p = strrchr(pinfo2->printername, '\\');
2742
2743         if (!p) {
2744                 p = pinfo2->printername;
2745         } else {
2746                 p++;
2747         }
2748
2749         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2750 }
2751
2752 /*******************************************************************
2753  * fill a notify_info_data with the servicename
2754  ********************************************************************/
2755
2756 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2757                                       int snum,
2758                                       struct spoolss_Notify *data,
2759                                       print_queue_struct *queue,
2760                                       struct spoolss_PrinterInfo2 *pinfo2,
2761                                       TALLOC_CTX *mem_ctx)
2762 {
2763         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2764 }
2765
2766 /*******************************************************************
2767  * fill a notify_info_data with the port name
2768  ********************************************************************/
2769
2770 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2771                                      int snum,
2772                                      struct spoolss_Notify *data,
2773                                      print_queue_struct *queue,
2774                                      struct spoolss_PrinterInfo2 *pinfo2,
2775                                      TALLOC_CTX *mem_ctx)
2776 {
2777         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2778 }
2779
2780 /*******************************************************************
2781  * fill a notify_info_data with the printername
2782  * but it doesn't exist, have to see what to do
2783  ********************************************************************/
2784
2785 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2786                                        int snum,
2787                                        struct spoolss_Notify *data,
2788                                        print_queue_struct *queue,
2789                                        struct spoolss_PrinterInfo2 *pinfo2,
2790                                        TALLOC_CTX *mem_ctx)
2791 {
2792         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2793 }
2794
2795 /*******************************************************************
2796  * fill a notify_info_data with the comment
2797  ********************************************************************/
2798
2799 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2800                                    int snum,
2801                                    struct spoolss_Notify *data,
2802                                    print_queue_struct *queue,
2803                                    struct spoolss_PrinterInfo2 *pinfo2,
2804                                    TALLOC_CTX *mem_ctx)
2805 {
2806         const char *p;
2807
2808         if (*pinfo2->comment == '\0') {
2809                 p = lp_comment(talloc_tos(), snum);
2810         } else {
2811                 p = pinfo2->comment;
2812         }
2813
2814         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2815 }
2816
2817 /*******************************************************************
2818  * fill a notify_info_data with the comment
2819  * location = "Room 1, floor 2, building 3"
2820  ********************************************************************/
2821
2822 static void spoolss_notify_location(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         const char *loc = pinfo2->location;
2830         NTSTATUS status;
2831
2832         status = printer_list_get_printer(mem_ctx,
2833                                           pinfo2->sharename,
2834                                           NULL,
2835                                           &loc,
2836                                           NULL);
2837         if (NT_STATUS_IS_OK(status)) {
2838                 if (loc == NULL) {
2839                         loc = pinfo2->location;
2840                 }
2841         }
2842
2843         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2844 }
2845
2846 /*******************************************************************
2847  * fill a notify_info_data with the device mode
2848  * jfm:xxxx don't to it for know but that's a real problem !!!
2849  ********************************************************************/
2850
2851 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2852                                    int snum,
2853                                    struct spoolss_Notify *data,
2854                                    print_queue_struct *queue,
2855                                    struct spoolss_PrinterInfo2 *pinfo2,
2856                                    TALLOC_CTX *mem_ctx)
2857 {
2858         /* for a dummy implementation we have to zero the fields */
2859         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2860 }
2861
2862 /*******************************************************************
2863  * fill a notify_info_data with the separator file name
2864  ********************************************************************/
2865
2866 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2867                                    int snum,
2868                                    struct spoolss_Notify *data,
2869                                    print_queue_struct *queue,
2870                                    struct spoolss_PrinterInfo2 *pinfo2,
2871                                    TALLOC_CTX *mem_ctx)
2872 {
2873         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2874 }
2875
2876 /*******************************************************************
2877  * fill a notify_info_data with the print processor
2878  * jfm:xxxx return always winprint to indicate we don't do anything to it
2879  ********************************************************************/
2880
2881 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2882                                            int snum,
2883                                            struct spoolss_Notify *data,
2884                                            print_queue_struct *queue,
2885                                            struct spoolss_PrinterInfo2 *pinfo2,
2886                                            TALLOC_CTX *mem_ctx)
2887 {
2888         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2889 }
2890
2891 /*******************************************************************
2892  * fill a notify_info_data with the print processor options
2893  * jfm:xxxx send an empty string
2894  ********************************************************************/
2895
2896 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2897                                       int snum,
2898                                       struct spoolss_Notify *data,
2899                                       print_queue_struct *queue,
2900                                       struct spoolss_PrinterInfo2 *pinfo2,
2901                                       TALLOC_CTX *mem_ctx)
2902 {
2903         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2904 }
2905
2906 /*******************************************************************
2907  * fill a notify_info_data with the data type
2908  * jfm:xxxx always send RAW as data type
2909  ********************************************************************/
2910
2911 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2912                                     int snum,
2913                                     struct spoolss_Notify *data,
2914                                     print_queue_struct *queue,
2915                                     struct spoolss_PrinterInfo2 *pinfo2,
2916                                     TALLOC_CTX *mem_ctx)
2917 {
2918         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2919 }
2920
2921 /*******************************************************************
2922  * fill a notify_info_data with the security descriptor
2923  * jfm:xxxx send an null pointer to say no security desc
2924  * have to implement security before !
2925  ********************************************************************/
2926
2927 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2928                                          int snum,
2929                                          struct spoolss_Notify *data,
2930                                          print_queue_struct *queue,
2931                                          struct spoolss_PrinterInfo2 *pinfo2,
2932                                          TALLOC_CTX *mem_ctx)
2933 {
2934         if (pinfo2->secdesc == NULL) {
2935                 data->data.sd.sd = NULL;
2936         } else {
2937                 data->data.sd.sd = security_descriptor_copy(mem_ctx,
2938                                                             pinfo2->secdesc);
2939         }
2940         data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2941                                                              0);
2942 }
2943
2944 /*******************************************************************
2945  * fill a notify_info_data with the attributes
2946  * jfm:xxxx a samba printer is always shared
2947  ********************************************************************/
2948
2949 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2950                                       int snum,
2951                                       struct spoolss_Notify *data,
2952                                       print_queue_struct *queue,
2953                                       struct spoolss_PrinterInfo2 *pinfo2,
2954                                       TALLOC_CTX *mem_ctx)
2955 {
2956         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2957 }
2958
2959 /*******************************************************************
2960  * fill a notify_info_data with the priority
2961  ********************************************************************/
2962
2963 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2964                                     int snum,
2965                                     struct spoolss_Notify *data,
2966                                     print_queue_struct *queue,
2967                                     struct spoolss_PrinterInfo2 *pinfo2,
2968                                     TALLOC_CTX *mem_ctx)
2969 {
2970         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2971 }
2972
2973 /*******************************************************************
2974  * fill a notify_info_data with the default priority
2975  ********************************************************************/
2976
2977 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2978                                             int snum,
2979                                             struct spoolss_Notify *data,
2980                                             print_queue_struct *queue,
2981                                             struct spoolss_PrinterInfo2 *pinfo2,
2982                                             TALLOC_CTX *mem_ctx)
2983 {
2984         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2985 }
2986
2987 /*******************************************************************
2988  * fill a notify_info_data with the start time
2989  ********************************************************************/
2990
2991 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2992                                       int snum,
2993                                       struct spoolss_Notify *data,
2994                                       print_queue_struct *queue,
2995                                       struct spoolss_PrinterInfo2 *pinfo2,
2996                                       TALLOC_CTX *mem_ctx)
2997 {
2998         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2999 }
3000
3001 /*******************************************************************
3002  * fill a notify_info_data with the until time
3003  ********************************************************************/
3004
3005 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3006                                       int snum,
3007                                       struct spoolss_Notify *data,
3008                                       print_queue_struct *queue,
3009                                       struct spoolss_PrinterInfo2 *pinfo2,
3010                                       TALLOC_CTX *mem_ctx)
3011 {
3012         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3013 }
3014
3015 /*******************************************************************
3016  * fill a notify_info_data with the status
3017  ********************************************************************/
3018
3019 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3020                                   int snum,
3021                                   struct spoolss_Notify *data,
3022                                   print_queue_struct *queue,
3023                                   struct spoolss_PrinterInfo2 *pinfo2,
3024                                   TALLOC_CTX *mem_ctx)
3025 {
3026         print_status_struct status;
3027
3028         print_queue_length(msg_ctx, snum, &status);
3029         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3030 }
3031
3032 /*******************************************************************
3033  * fill a notify_info_data with the number of jobs queued
3034  ********************************************************************/
3035
3036 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3037                                  int snum,
3038                                  struct spoolss_Notify *data,
3039                                  print_queue_struct *queue,
3040                                  struct spoolss_PrinterInfo2 *pinfo2,
3041                                  TALLOC_CTX *mem_ctx)
3042 {
3043         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3044                 data, print_queue_length(msg_ctx, snum, NULL));
3045 }
3046
3047 /*******************************************************************
3048  * fill a notify_info_data with the average ppm
3049  ********************************************************************/
3050
3051 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3052                                        int snum,
3053                                        struct spoolss_Notify *data,
3054                                        print_queue_struct *queue,
3055                                        struct spoolss_PrinterInfo2 *pinfo2,
3056                                        TALLOC_CTX *mem_ctx)
3057 {
3058         /* always respond 8 pages per minutes */
3059         /* a little hard ! */
3060         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3061 }
3062
3063 /*******************************************************************
3064  * fill a notify_info_data with username
3065  ********************************************************************/
3066
3067 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3068                                     int snum,
3069                                     struct spoolss_Notify *data,
3070                                     print_queue_struct *queue,
3071                                     struct spoolss_PrinterInfo2 *pinfo2,
3072                                     TALLOC_CTX *mem_ctx)
3073 {
3074         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3075 }
3076
3077 /*******************************************************************
3078  * fill a notify_info_data with job status
3079  ********************************************************************/
3080
3081 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3082                                       int snum,
3083                                       struct spoolss_Notify *data,
3084                                       print_queue_struct *queue,
3085                                       struct spoolss_PrinterInfo2 *pinfo2,
3086                                       TALLOC_CTX *mem_ctx)
3087 {
3088         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3089 }
3090
3091 /*******************************************************************
3092  * fill a notify_info_data with job name
3093  ********************************************************************/
3094
3095 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3096                                     int snum,
3097                                     struct spoolss_Notify *data,
3098                                     print_queue_struct *queue,
3099                                     struct spoolss_PrinterInfo2 *pinfo2,
3100                                     TALLOC_CTX *mem_ctx)
3101 {
3102         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3103 }
3104
3105 /*******************************************************************
3106  * fill a notify_info_data with job status
3107  ********************************************************************/
3108
3109 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3110                                              int snum,
3111                                              struct spoolss_Notify *data,
3112                                              print_queue_struct *queue,
3113                                              struct spoolss_PrinterInfo2 *pinfo2,
3114                                              TALLOC_CTX *mem_ctx)
3115 {
3116         /*
3117          * Now we're returning job status codes we just return a "" here. JRA.
3118          */
3119
3120         const char *p = "";
3121
3122 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3123         p = "unknown";
3124
3125         switch (queue->status) {
3126         case LPQ_QUEUED:
3127                 p = "Queued";
3128                 break;
3129         case LPQ_PAUSED:
3130                 p = "";    /* NT provides the paused string */
3131                 break;
3132         case LPQ_SPOOLING:
3133                 p = "Spooling";
3134                 break;
3135         case LPQ_PRINTING:
3136                 p = "Printing";
3137                 break;
3138         }
3139 #endif /* NO LONGER NEEDED. */
3140
3141         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3142 }
3143
3144 /*******************************************************************
3145  * fill a notify_info_data with job time
3146  ********************************************************************/
3147
3148 static void spoolss_notify_job_time(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         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3156 }
3157
3158 /*******************************************************************
3159  * fill a notify_info_data with job size
3160  ********************************************************************/
3161
3162 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3163                                     int snum,
3164                                     struct spoolss_Notify *data,
3165                                     print_queue_struct *queue,
3166                                     struct spoolss_PrinterInfo2 *pinfo2,
3167                                     TALLOC_CTX *mem_ctx)
3168 {
3169         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3170 }
3171
3172 /*******************************************************************
3173  * fill a notify_info_data with page info
3174  ********************************************************************/
3175 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3176                                        int snum,
3177                                 struct spoolss_Notify *data,
3178                                 print_queue_struct *queue,
3179                                 struct spoolss_PrinterInfo2 *pinfo2,
3180                                 TALLOC_CTX *mem_ctx)
3181 {
3182         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3183 }
3184
3185 /*******************************************************************
3186  * fill a notify_info_data with pages printed info.
3187  ********************************************************************/
3188 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3189                                          int snum,
3190                                 struct spoolss_Notify *data,
3191                                 print_queue_struct *queue,
3192                                 struct spoolss_PrinterInfo2 *pinfo2,
3193                                 TALLOC_CTX *mem_ctx)
3194 {
3195         /* Add code when back-end tracks this */
3196         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3197 }
3198
3199 /*******************************************************************
3200  Fill a notify_info_data with job position.
3201  ********************************************************************/
3202
3203 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3204                                         int snum,
3205                                         struct spoolss_Notify *data,
3206                                         print_queue_struct *queue,
3207                                         struct spoolss_PrinterInfo2 *pinfo2,
3208                                         TALLOC_CTX *mem_ctx)
3209 {
3210         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3211 }
3212
3213 /*******************************************************************
3214  Fill a notify_info_data with submitted time.
3215  ********************************************************************/
3216
3217 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3218                                           int snum,
3219                                           struct spoolss_Notify *data,
3220                                           print_queue_struct *queue,
3221                                           struct spoolss_PrinterInfo2 *pinfo2,
3222                                           TALLOC_CTX *mem_ctx)
3223 {
3224         data->data.string.string = NULL;
3225         data->data.string.size = 0;
3226
3227         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3228                                &data->data.string.string,
3229                                &data->data.string.size);
3230
3231 }
3232
3233 struct s_notify_info_data_table
3234 {
3235         enum spoolss_NotifyType type;
3236         uint16_t field;
3237         const char *name;
3238         enum spoolss_NotifyTable variable_type;
3239         void (*fn) (struct messaging_context *msg_ctx,
3240                     int snum, struct spoolss_Notify *data,
3241                     print_queue_struct *queue,
3242                     struct spoolss_PrinterInfo2 *pinfo2,
3243                     TALLOC_CTX *mem_ctx);
3244 };
3245
3246 /* A table describing the various print notification constants and
3247    whether the notification data is a pointer to a variable sized
3248    buffer, a one value uint32_t or a two value uint32_t. */
3249
3250 static const struct s_notify_info_data_table notify_info_data_table[] =
3251 {
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3278 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3279 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3280 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3281 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3282 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3283 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3284 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3285 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3286 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3287 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3288 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3289 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3290 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3291 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3301 };
3302
3303 /*******************************************************************
3304  Return the variable_type of info_data structure.
3305 ********************************************************************/
3306
3307 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3308                                                                   uint16_t field)
3309 {
3310         int i=0;
3311
3312         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3313                 if ( (notify_info_data_table[i].type == type) &&
3314                      (notify_info_data_table[i].field == field) ) {
3315                         return notify_info_data_table[i].variable_type;
3316                 }
3317         }
3318
3319         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3320
3321         return (enum spoolss_NotifyTable) 0;
3322 }
3323
3324 /****************************************************************************
3325 ****************************************************************************/
3326
3327 static bool search_notify(enum spoolss_NotifyType type,
3328                           uint16_t field,
3329                           int *value)
3330 {
3331         int i;
3332
3333         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3334                 if (notify_info_data_table[i].type == type &&
3335                     notify_info_data_table[i].field == field &&
3336                     notify_info_data_table[i].fn != NULL) {
3337                         *value = i;
3338                         return true;
3339                 }
3340         }
3341
3342         return false;
3343 }
3344
3345 /****************************************************************************
3346 ****************************************************************************/
3347
3348 static void construct_info_data(struct spoolss_Notify *info_data,
3349                                 enum spoolss_NotifyType type,
3350                                 uint16_t field, int id)
3351 {
3352         info_data->type                 = type;
3353         info_data->field.field          = field;
3354         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3355         info_data->job_id               = id;
3356 }
3357
3358 /*******************************************************************
3359  *
3360  * fill a notify_info struct with info asked
3361  *
3362  ********************************************************************/
3363
3364 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3365                                           struct printer_handle *print_hnd,
3366                                           struct spoolss_NotifyInfo *info,
3367                                           struct spoolss_PrinterInfo2 *pinfo2,
3368                                           int snum,
3369                                           const struct spoolss_NotifyOptionType *option_type,
3370                                           uint32_t id,
3371                                           TALLOC_CTX *mem_ctx)
3372 {
3373         int field_num,j;
3374         enum spoolss_NotifyType type;
3375         uint16_t field;
3376
3377         struct spoolss_Notify *current_data;
3378
3379         type = option_type->type;
3380
3381         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3382                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3383                 option_type->count, lp_servicename(talloc_tos(), snum)));
3384
3385         for(field_num=0; field_num < option_type->count; field_num++) {
3386                 field = option_type->fields[field_num].field;
3387
3388                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3389
3390                 if (!search_notify(type, field, &j) )
3391                         continue;
3392
3393                 info->notifies = talloc_realloc(info, info->notifies,
3394                                                       struct spoolss_Notify,
3395                                                       info->count + 1);
3396                 if (info->notifies == NULL) {
3397                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3398                         return false;
3399                 }
3400
3401                 current_data = &info->notifies[info->count];
3402
3403                 construct_info_data(current_data, type, field, id);
3404
3405                 DEBUG(10, ("construct_notify_printer_info: "
3406                            "calling [%s]  snum=%d  printername=[%s])\n",
3407                            notify_info_data_table[j].name, snum,
3408                            pinfo2->printername));
3409
3410                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3411                                              NULL, pinfo2, mem_ctx);
3412
3413                 info->count++;
3414         }
3415
3416         return true;
3417 }
3418
3419 /*******************************************************************
3420  *
3421  * fill a notify_info struct with info asked
3422  *
3423  ********************************************************************/
3424
3425 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3426                                        print_queue_struct *queue,
3427                                        struct spoolss_NotifyInfo *info,
3428                                        struct spoolss_PrinterInfo2 *pinfo2,
3429                                        int snum,
3430                                        const struct spoolss_NotifyOptionType *option_type,
3431                                        uint32_t id,
3432                                        TALLOC_CTX *mem_ctx)
3433 {
3434         int field_num,j;
3435         enum spoolss_NotifyType type;
3436         uint16_t field;
3437         struct spoolss_Notify *current_data;
3438
3439         DEBUG(4,("construct_notify_jobs_info\n"));
3440
3441         type = option_type->type;
3442
3443         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3444                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3445                 option_type->count));
3446
3447         for(field_num=0; field_num<option_type->count; field_num++) {
3448                 field = option_type->fields[field_num].field;
3449
3450                 if (!search_notify(type, field, &j) )
3451                         continue;
3452
3453                 info->notifies = talloc_realloc(info, info->notifies,
3454                                                       struct spoolss_Notify,
3455                                                       info->count + 1);
3456                 if (info->notifies == NULL) {
3457                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3458                         return false;
3459                 }
3460
3461                 current_data=&(info->notifies[info->count]);
3462
3463                 construct_info_data(current_data, type, field, id);
3464                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3465                                              queue, pinfo2, mem_ctx);
3466                 info->count++;
3467         }
3468
3469         return true;
3470 }
3471
3472 /*
3473  * JFM: The enumeration is not that simple, it's even non obvious.
3474  *
3475  * let's take an example: I want to monitor the PRINTER SERVER for
3476  * the printer's name and the number of jobs currently queued.
3477  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3478  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3479  *
3480  * I have 3 printers on the back of my server.
3481  *
3482  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3483  * structures.
3484  *   Number     Data                    Id
3485  *      1       printer 1 name          1
3486  *      2       printer 1 cjob          1
3487  *      3       printer 2 name          2
3488  *      4       printer 2 cjob          2
3489  *      5       printer 3 name          3
3490  *      6       printer 3 name          3
3491  *
3492  * that's the print server case, the printer case is even worse.
3493  */
3494
3495 /*******************************************************************
3496  *
3497  * enumerate all printers on the printserver
3498  * fill a notify_info struct with info asked
3499  *
3500  ********************************************************************/
3501
3502 static WERROR printserver_notify_info(struct pipes_struct *p,
3503                                       struct policy_handle *hnd,
3504                                       struct spoolss_NotifyInfo *info,
3505                                       TALLOC_CTX *mem_ctx)
3506 {
3507         int snum;
3508         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3509         int n_services=lp_numservices();
3510         int i;
3511         struct spoolss_NotifyOption *option;
3512         struct spoolss_NotifyOptionType option_type;
3513         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3514         WERROR result;
3515
3516         DEBUG(4,("printserver_notify_info\n"));
3517
3518         if (!Printer)
3519                 return WERR_INVALID_HANDLE;
3520
3521         option = Printer->notify.option;
3522
3523         info->version   = 2;
3524         info->notifies  = NULL;
3525         info->count     = 0;
3526
3527         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3528            sending a ffpcn() request first */
3529
3530         if ( !option )
3531                 return WERR_INVALID_HANDLE;
3532
3533         for (i=0; i<option->count; i++) {
3534                 option_type = option->types[i];
3535
3536                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3537                         continue;
3538
3539                 for (snum = 0; snum < n_services; snum++) {
3540                         if (!lp_browseable(snum) ||
3541                             !lp_snum_ok(snum) ||
3542                             !lp_printable(snum)) {
3543                                 continue; /* skip */
3544                         }
3545
3546                         /* Maybe we should use the SYSTEM session_info here... */
3547                         result = winreg_get_printer_internal(mem_ctx,
3548                                                     get_session_info_system(),
3549                                                     p->msg_ctx,
3550                                                     lp_servicename(talloc_tos(), snum),
3551                                                     &pinfo2);
3552                         if (!W_ERROR_IS_OK(result)) {
3553                                 DEBUG(4, ("printserver_notify_info: "
3554                                           "Failed to get printer [%s]\n",
3555                                           lp_servicename(talloc_tos(), snum)));
3556                                 continue;
3557                         }
3558
3559
3560                         construct_notify_printer_info(p->msg_ctx,
3561                                                       Printer, info,
3562                                                       pinfo2, snum,
3563                                                       &option_type, snum,
3564                                                       mem_ctx);
3565
3566                         TALLOC_FREE(pinfo2);
3567                 }
3568         }
3569
3570 #if 0
3571         /*
3572          * Debugging information, don't delete.
3573          */
3574
3575         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3576         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3577         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3578
3579         for (i=0; i<info->count; i++) {
3580                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3581                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3582                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3583         }
3584 #endif
3585
3586         return WERR_OK;
3587 }
3588
3589 /*******************************************************************
3590  *
3591  * fill a notify_info struct with info asked
3592  *
3593  ********************************************************************/
3594
3595 static WERROR printer_notify_info(struct pipes_struct *p,
3596                                   struct policy_handle *hnd,
3597                                   struct spoolss_NotifyInfo *info,
3598                                   TALLOC_CTX *mem_ctx)
3599 {
3600         int snum;
3601         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3602         int i;
3603         uint32_t id;
3604         struct spoolss_NotifyOption *option;
3605         struct spoolss_NotifyOptionType option_type;
3606         int count,j;
3607         print_queue_struct *queue=NULL;
3608         print_status_struct status;
3609         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3610         WERROR result;
3611         struct tdb_print_db *pdb;
3612
3613         DEBUG(4,("printer_notify_info\n"));
3614
3615         if (!Printer)
3616                 return WERR_INVALID_HANDLE;
3617
3618         option = Printer->notify.option;
3619         id = 0x0;
3620
3621         info->version   = 2;
3622         info->notifies  = NULL;
3623         info->count     = 0;
3624
3625         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3626            sending a ffpcn() request first */
3627
3628         if ( !option )
3629                 return WERR_INVALID_HANDLE;
3630
3631         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3632                 return WERR_INVALID_HANDLE;
3633         }
3634
3635         pdb = get_print_db_byname(Printer->sharename);
3636         if (pdb == NULL) {
3637                 return WERR_INVALID_HANDLE;
3638         }
3639
3640         /* Maybe we should use the SYSTEM session_info here... */
3641         result = winreg_get_printer_internal(mem_ctx,
3642                                     get_session_info_system(),
3643                                     p->msg_ctx,
3644                                     lp_servicename(talloc_tos(), snum), &pinfo2);
3645         if (!W_ERROR_IS_OK(result)) {
3646                 result = WERR_INVALID_HANDLE;
3647                 goto err_pdb_drop;
3648         }
3649
3650         /*
3651          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3652          * correct servername.
3653          */
3654         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3655         if (pinfo2->servername == NULL) {
3656                 result = WERR_NOT_ENOUGH_MEMORY;
3657                 goto err_pdb_drop;
3658         }
3659
3660         for (i = 0; i < option->count; i++) {
3661                 option_type = option->types[i];
3662
3663                 switch (option_type.type) {
3664                 case PRINTER_NOTIFY_TYPE:
3665                         if (construct_notify_printer_info(p->msg_ctx,
3666                                                           Printer, info,
3667                                                           pinfo2, snum,
3668                                                           &option_type, id,
3669                                                           mem_ctx)) {
3670                                 id--;
3671                         }
3672                         break;
3673
3674                 case JOB_NOTIFY_TYPE:
3675
3676                         count = print_queue_status(p->msg_ctx, snum, &queue,
3677                                                    &status);
3678
3679                         for (j = 0; j < count; j++) {
3680                                 uint32_t jobid;
3681                                 jobid = sysjob_to_jobid_pdb(pdb,
3682                                                             queue[j].sysjob);
3683                                 if (jobid == (uint32_t)-1) {
3684                                         DEBUG(2, ("ignoring untracked job %d\n",
3685                                                   queue[j].sysjob));
3686                                         continue;
3687                                 }
3688                                 /* FIXME check return value */
3689                                 construct_notify_jobs_info(p->msg_ctx,
3690                                                            &queue[j], info,
3691                                                            pinfo2, snum,
3692                                                            &option_type,
3693                                                            jobid,
3694                                                            mem_ctx);
3695                         }
3696
3697                         SAFE_FREE(queue);
3698                         break;
3699                 }
3700         }
3701
3702         /*
3703          * Debugging information, don't delete.
3704          */
3705         /*
3706         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3707         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3708         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3709
3710         for (i=0; i<info->count; i++) {
3711                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3712                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3713                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3714         }
3715         */
3716
3717         talloc_free(pinfo2);
3718         result = WERR_OK;
3719 err_pdb_drop:
3720         release_print_db(pdb);
3721         return result;
3722 }
3723
3724 /****************************************************************
3725  _spoolss_RouterRefreshPrinterChangeNotify
3726 ****************************************************************/
3727
3728 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3729                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3730 {
3731         struct spoolss_NotifyInfo *info;
3732
3733         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3734         WERROR result = WERR_INVALID_HANDLE;
3735
3736         /* we always have a spoolss_NotifyInfo struct */
3737         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3738         if (!info) {
3739                 result = WERR_NOT_ENOUGH_MEMORY;
3740                 goto done;
3741         }
3742
3743         *r->out.info = info;
3744
3745         if (!Printer) {
3746                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3747                         "Invalid handle (%s:%u:%u).\n",
3748                         OUR_HANDLE(r->in.handle)));
3749                 goto done;
3750         }
3751
3752         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3753
3754         /*
3755          *      We are now using the change value, and
3756          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3757          *      I don't have a global notification system, I'm sending back all the
3758          *      information even when _NOTHING_ has changed.
3759          */
3760
3761         /* We need to keep track of the change value to send back in
3762            RRPCN replies otherwise our updates are ignored. */
3763
3764         Printer->notify.fnpcn = true;
3765
3766         if (Printer->notify.cli_chan != NULL &&
3767             Printer->notify.cli_chan->active_connections > 0) {
3768                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3769                         "Saving change value in request [%x]\n",
3770                         r->in.change_low));
3771                 Printer->notify.change = r->in.change_low;
3772         }
3773
3774         /* just ignore the spoolss_NotifyOption */
3775
3776         switch (Printer->printer_type) {
3777                 case SPLHND_SERVER:
3778                         result = printserver_notify_info(p, r->in.handle,
3779                                                          info, p->mem_ctx);
3780                         break;
3781
3782                 case SPLHND_PRINTER:
3783                         result = printer_notify_info(p, r->in.handle,
3784                                                      info, p->mem_ctx);
3785                         break;
3786         }
3787
3788         Printer->notify.fnpcn = false;
3789
3790 done:
3791         return result;
3792 }
3793
3794 /********************************************************************
3795  ********************************************************************/
3796
3797 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3798                                  const char *servername,
3799                                  const char *printername,
3800                                  const char **printername_p)
3801 {
3802         /* FIXME: add lp_force_printername() */
3803
3804         if (servername == NULL) {
3805                 *printername_p = talloc_strdup(mem_ctx, printername);
3806                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3807                 return WERR_OK;
3808         }
3809
3810         if (servername[0] == '\\' && servername[1] == '\\') {
3811                 servername += 2;
3812         }
3813
3814         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3815         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3816
3817         return WERR_OK;
3818 }
3819
3820 /********************************************************************
3821  ********************************************************************/
3822
3823 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3824                                           const char *printername)
3825 {
3826         if (dm == NULL) {
3827                 return;
3828         }
3829
3830         dm->devicename = talloc_strndup(dm, printername,
3831                                         MIN(strlen(printername), 31));
3832 }
3833
3834 /********************************************************************
3835  * construct_printer_info_0
3836  * fill a printer_info_0 struct
3837  ********************************************************************/
3838
3839 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3840                                       const struct auth_session_info *session_info,
3841                                       struct messaging_context *msg_ctx,
3842                                       struct spoolss_PrinterInfo2 *info2,
3843                                       const char *servername,
3844                                       struct spoolss_PrinterInfo0 *r,
3845                                       int snum)
3846 {
3847         int count;
3848         struct printer_session_counter *session_counter;
3849         struct timeval setuptime;
3850         print_status_struct status;
3851         WERROR result;
3852         int os_major, os_minor, os_build;
3853         const char *architecture;
3854         uint32_t processor_architecture, processor_type;
3855
3856         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3857         if (!W_ERROR_IS_OK(result)) {
3858                 return result;
3859         }
3860
3861         if (servername) {
3862                 r->servername = talloc_strdup(mem_ctx, servername);
3863                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3864         } else {
3865                 r->servername = NULL;
3866         }
3867
3868         count = print_queue_length(msg_ctx, snum, &status);
3869
3870         /* check if we already have a counter for this printer */
3871         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3872                 if (session_counter->snum == snum)
3873                         break;
3874         }
3875
3876         /* it's the first time, add it to the list */
3877         if (session_counter == NULL) {
3878                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3879                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3880                 session_counter->snum           = snum;
3881                 session_counter->counter        = 0;
3882                 DLIST_ADD(counter_list, session_counter);
3883         }
3884
3885         /* increment it */
3886         session_counter->counter++;
3887
3888         r->cjobs                        = count;
3889         r->total_jobs                   = 0;
3890         r->total_bytes                  = 0;
3891
3892         get_startup_time(&setuptime);
3893         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3894
3895         /* JFM:
3896          * the global_counter should be stored in a TDB as it's common to all the clients
3897          * and should be zeroed on samba startup
3898          */
3899         r->global_counter               = session_counter->counter;
3900         r->total_pages                  = 0;
3901
3902         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3903         os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
3904                                "spoolss", "os_major",
3905                                GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
3906         os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
3907                                "spoolss", "os_minor",
3908                                GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
3909         os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
3910                                "spoolss", "os_build",
3911                                GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
3912
3913         SCVAL(&r->version, 0, os_major);
3914         SCVAL(&r->version, 1, os_minor);
3915         SSVAL(&r->version, 2, os_build);
3916
3917         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
3918                                             "spoolss",
3919                                             "architecture",
3920                                             GLOBAL_SPOOLSS_ARCHITECTURE);
3921
3922         if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
3923                 processor_architecture  = PROCESSOR_ARCHITECTURE_AMD64;
3924                 processor_type          = PROCESSOR_AMD_X8664;
3925         } else {
3926                 processor_architecture  = PROCESSOR_ARCHITECTURE_INTEL;
3927                 processor_type          = PROCESSOR_INTEL_PENTIUM;
3928         }
3929
3930         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3931         r->spooling                     = 0;
3932         r->max_spooling                 = 0;
3933         r->session_counter              = session_counter->counter;
3934         r->num_error_out_of_paper       = 0x0;
3935         r->num_error_not_ready          = 0x0;          /* number of print failure */
3936         r->job_error                    = 0x0;
3937         r->number_of_processors         = 0x1;
3938         r->processor_type               = processor_type;
3939         r->high_part_total_bytes        = 0x0;
3940
3941         /* ChangeID in milliseconds*/
3942         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3943                                     info2->sharename, &r->change_id);
3944
3945         r->last_error                   = WERR_OK;
3946         r->status                       = nt_printq_status(status.status);
3947         r->enumerate_network_printers   = 0x0;
3948         r->c_setprinter                 = 0x0;
3949         r->processor_architecture       = processor_architecture;
3950         r->processor_level              = 0x6;          /* 6  ???*/
3951         r->ref_ic                       = 0;
3952         r->reserved2                    = 0;
3953         r->reserved3                    = 0;
3954
3955         return WERR_OK;
3956 }
3957
3958
3959 /********************************************************************
3960  * construct_printer_info1
3961  * fill a spoolss_PrinterInfo1 struct
3962 ********************************************************************/
3963
3964 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3965                                       const struct spoolss_PrinterInfo2 *info2,
3966                                       uint32_t flags,
3967                                       const char *servername,
3968                                       struct spoolss_PrinterInfo1 *r,
3969                                       int snum)
3970 {
3971         WERROR result;
3972
3973         r->flags                = flags;
3974
3975         if (info2->comment == NULL || info2->comment[0] == '\0') {
3976                 r->comment      = lp_comment(mem_ctx, snum);
3977         } else {
3978                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3979         }
3980         W_ERROR_HAVE_NO_MEMORY(r->comment);
3981
3982         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3983         if (!W_ERROR_IS_OK(result)) {
3984                 return result;
3985         }
3986
3987         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3988                                                   r->name,
3989                                                   info2->drivername,
3990                                                   r->comment);
3991         W_ERROR_HAVE_NO_MEMORY(r->description);
3992
3993         return WERR_OK;
3994 }
3995
3996 /********************************************************************
3997  * construct_printer_info2
3998  * fill a spoolss_PrinterInfo2 struct
3999 ********************************************************************/
4000
4001 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4002                                       struct messaging_context *msg_ctx,
4003                                       const struct spoolss_PrinterInfo2 *info2,
4004                                       const char *servername,
4005                                       struct spoolss_PrinterInfo2 *r,
4006                                       int snum)
4007 {
4008         int count;
4009         print_status_struct status;
4010         WERROR result;
4011
4012         count = print_queue_length(msg_ctx, snum, &status);
4013
4014         if (servername) {
4015                 r->servername           = talloc_strdup(mem_ctx, servername);
4016                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4017         } else {
4018                 r->servername           = NULL;
4019         }
4020
4021         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4022         if (!W_ERROR_IS_OK(result)) {
4023                 return result;
4024         }
4025
4026         r->sharename            = lp_servicename(mem_ctx, snum);
4027         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4028         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4029         W_ERROR_HAVE_NO_MEMORY(r->portname);
4030         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4031         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4032
4033         if (info2->comment[0] == '\0') {
4034                 r->comment      = lp_comment(mem_ctx, snum);
4035         } else {
4036                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4037         }
4038         W_ERROR_HAVE_NO_MEMORY(r->comment);
4039
4040         r->location     = talloc_strdup(mem_ctx, info2->location);
4041         if (info2->location[0] == '\0') {
4042                 const char *loc = NULL;
4043                 NTSTATUS nt_status;
4044
4045                 nt_status = printer_list_get_printer(mem_ctx,
4046                                                      info2->sharename,
4047                                                      NULL,
4048                                                      &loc,
4049                                                      NULL);
4050                 if (NT_STATUS_IS_OK(nt_status)) {
4051                         if (loc != NULL) {
4052                                 r->location = talloc_strdup(mem_ctx, loc);
4053                         }
4054                 }
4055         }
4056         W_ERROR_HAVE_NO_MEMORY(r->location);
4057
4058         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4059         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4060         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4061         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4062         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4063         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4064         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4065         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4066
4067         r->attributes           = info2->attributes;
4068
4069         r->priority             = info2->priority;
4070         r->defaultpriority      = info2->defaultpriority;
4071         r->starttime            = info2->starttime;
4072         r->untiltime            = info2->untiltime;
4073         r->status               = nt_printq_status(status.status);
4074         r->cjobs                = count;
4075         r->averageppm           = info2->averageppm;
4076
4077         if (info2->devmode != NULL) {
4078                 result = copy_devicemode(mem_ctx,
4079                                          info2->devmode,
4080                                          &r->devmode);
4081                 if (!W_ERROR_IS_OK(result)) {
4082                         return result;
4083                 }
4084         } else if (lp_default_devmode(snum)) {
4085                 result = spoolss_create_default_devmode(mem_ctx,
4086                                                         info2->printername,
4087                                                         &r->devmode);
4088                 if (!W_ERROR_IS_OK(result)) {
4089                         return result;
4090                 }
4091         } else {
4092                 r->devmode = NULL;
4093                 DEBUG(8,("Returning NULL Devicemode!\n"));
4094         }
4095
4096         compose_devicemode_devicename(r->devmode, r->printername);
4097
4098         r->secdesc = NULL;
4099
4100         if (info2->secdesc != NULL) {
4101                 /* don't use talloc_steal() here unless you do a deep steal of all
4102                    the SEC_DESC members */
4103
4104                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4105                 if (r->secdesc == NULL) {
4106                         return WERR_NOT_ENOUGH_MEMORY;
4107                 }
4108         }
4109
4110         return WERR_OK;
4111 }
4112
4113 /********************************************************************
4114  * construct_printer_info3
4115  * fill a spoolss_PrinterInfo3 struct
4116  ********************************************************************/
4117
4118 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4119                                       const struct spoolss_PrinterInfo2 *info2,
4120                                       const char *servername,
4121                                       struct spoolss_PrinterInfo3 *r,
4122                                       int snum)
4123 {
4124         /* These are the components of the SD we are returning. */
4125
4126         if (info2->secdesc != NULL) {
4127                 /* don't use talloc_steal() here unless you do a deep steal of all
4128                    the SEC_DESC members */
4129
4130                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4131                 if (r->secdesc == NULL) {
4132                         return WERR_NOT_ENOUGH_MEMORY;
4133                 }
4134         }
4135
4136         return WERR_OK;
4137 }
4138
4139 /********************************************************************
4140  * construct_printer_info4
4141  * fill a spoolss_PrinterInfo4 struct
4142  ********************************************************************/
4143
4144 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4145                                       const struct spoolss_PrinterInfo2 *info2,
4146                                       const char *servername,
4147                                       struct spoolss_PrinterInfo4 *r,
4148                                       int snum)
4149 {
4150         WERROR result;
4151
4152         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4153         if (!W_ERROR_IS_OK(result)) {
4154                 return result;
4155         }
4156
4157         if (servername) {
4158                 r->servername   = talloc_strdup(mem_ctx, servername);
4159                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4160         } else {
4161                 r->servername = NULL;
4162         }
4163
4164         r->attributes   = info2->attributes;
4165
4166         return WERR_OK;
4167 }
4168
4169 /********************************************************************
4170  * construct_printer_info5
4171  * fill a spoolss_PrinterInfo5 struct
4172  ********************************************************************/
4173
4174 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4175                                       const struct spoolss_PrinterInfo2 *info2,
4176                                       const char *servername,
4177                                       struct spoolss_PrinterInfo5 *r,
4178                                       int snum)
4179 {
4180         WERROR result;
4181
4182         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4183         if (!W_ERROR_IS_OK(result)) {
4184                 return result;
4185         }
4186
4187         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4188         W_ERROR_HAVE_NO_MEMORY(r->portname);
4189
4190         r->attributes   = info2->attributes;
4191
4192         /*
4193          * These two are not used by NT+ according to MSDN. However the values
4194          * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
4195          */
4196         r->device_not_selected_timeout          = 0xafc8; /* 45 sec */
4197         r->transmission_retry_timeout           = 0xafc8; /* 45 sec */
4198
4199         return WERR_OK;
4200 }
4201
4202 /********************************************************************
4203  * construct_printer_info_6
4204  * fill a spoolss_PrinterInfo6 struct
4205  ********************************************************************/
4206
4207 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4208                                       struct messaging_context *msg_ctx,
4209                                       const struct spoolss_PrinterInfo2 *info2,
4210                                       const char *servername,
4211                                       struct spoolss_PrinterInfo6 *r,
4212                                       int snum)
4213 {
4214         print_status_struct status;
4215
4216         print_queue_length(msg_ctx, snum, &status);
4217
4218         r->status = nt_printq_status(status.status);
4219
4220         return WERR_OK;
4221 }
4222
4223 /********************************************************************
4224  * construct_printer_info7
4225  * fill a spoolss_PrinterInfo7 struct
4226  ********************************************************************/
4227
4228 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4229                                       struct messaging_context *msg_ctx,
4230                                       const char *servername,
4231                                       struct spoolss_PrinterInfo7 *r,
4232                                       int snum)
4233 {
4234         const struct auth_session_info *session_info;
4235         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4236         char *printer;
4237         WERROR werr;
4238         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4239         if (tmp_ctx == NULL) {
4240                 return WERR_NOT_ENOUGH_MEMORY;
4241         }
4242
4243         session_info = get_session_info_system();
4244         SMB_ASSERT(session_info != NULL);
4245
4246         printer = lp_servicename(tmp_ctx, snum);
4247         if (printer == NULL) {
4248                 DEBUG(0, ("invalid printer snum %d\n", snum));
4249                 werr = WERR_INVALID_PARAMETER;
4250                 goto out_tmp_free;
4251         }
4252
4253         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4254                                  servername, printer, &pinfo2)) {
4255                 struct GUID guid;
4256                 char *guidstr;
4257                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4258                                            printer, &guid);
4259                 if (!W_ERROR_IS_OK(werr)) {
4260                         /*
4261                          * If we do not have a GUID entry in the registry, then
4262                          * try to retrieve it from AD and store it now.
4263                          */
4264                         werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4265                                                         &guid);
4266                         if (!W_ERROR_IS_OK(werr)) {
4267                                 DBG_NOTICE("Failed to retrieve GUID for "
4268                                            "printer [%s] from AD - %s\n",
4269                                            printer,
4270                                            win_errstr(werr));
4271                                 if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
4272                                         /*
4273                                          * If we did not find it in AD, then it
4274                                          * is unpublished and we should reflect
4275                                          * this in the registry and return
4276                                          * success.
4277                                          */
4278                                         DBG_WARNING("Unpublish printer [%s]\n",
4279                                                     pinfo2->sharename);
4280                                         nt_printer_publish(tmp_ctx,
4281                                                            session_info,
4282                                                            msg_ctx,
4283                                                            pinfo2,
4284                                                            DSPRINT_UNPUBLISH);
4285                                         r->guid = talloc_strdup(mem_ctx, "");
4286                                         r->action = DSPRINT_UNPUBLISH;
4287
4288                                         if (r->guid == NULL) {
4289                                                 werr = WERR_NOT_ENOUGH_MEMORY;
4290                                         } else {
4291                                                 werr = WERR_OK;
4292                                         }
4293                                 }
4294                                 goto out_tmp_free;
4295                         }
4296
4297                         werr = nt_printer_guid_store(msg_ctx, printer, guid);
4298                         if (!W_ERROR_IS_OK(werr)) {
4299                                 DEBUG(3, ("failed to store printer %s guid\n",
4300                                           printer));
4301                         }
4302                 }
4303
4304                 /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
4305                 guidstr = GUID_string2(mem_ctx, &guid);
4306                 if (guidstr == NULL) {
4307                         werr = WERR_NOT_ENOUGH_MEMORY;
4308                         goto out_tmp_free;
4309                 }
4310                 /* Convert GUID string to uppercase otherwise printers
4311                  * are pruned */
4312                 r->guid = talloc_strdup_upper(mem_ctx, guidstr);
4313                 r->action = DSPRINT_PUBLISH;
4314
4315                 TALLOC_FREE(guidstr);
4316         } else {
4317                 r->guid = talloc_strdup(mem_ctx, "");
4318                 r->action = DSPRINT_UNPUBLISH;
4319         }
4320         if (r->guid == NULL) {
4321                 werr = WERR_NOT_ENOUGH_MEMORY;
4322                 goto out_tmp_free;
4323         }
4324
4325         werr = WERR_OK;
4326 out_tmp_free:
4327         talloc_free(tmp_ctx);
4328         return werr;
4329 }
4330
4331 /********************************************************************
4332  * construct_printer_info8
4333  * fill a spoolss_PrinterInfo8 struct
4334  ********************************************************************/
4335
4336 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4337                                       const struct spoolss_PrinterInfo2 *info2,
4338                                       const char *servername,
4339                                       struct spoolss_DeviceModeInfo *r,
4340                                       int snum)
4341 {
4342         WERROR result;
4343         const char *printername;
4344
4345         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4346         if (!W_ERROR_IS_OK(result)) {
4347                 return result;
4348         }
4349
4350         if (info2->devmode != NULL) {
4351                 result = copy_devicemode(mem_ctx,
4352                                          info2->devmode,
4353                                          &r->devmode);
4354                 if (!W_ERROR_IS_OK(result)) {
4355                         return result;
4356                 }
4357         } else if (lp_default_devmode(snum)) {
4358                 result = spoolss_create_default_devmode(mem_ctx,
4359                                                         info2->printername,
4360                                                         &r->devmode);
4361                 if (!W_ERROR_IS_OK(result)) {
4362                         return result;
4363                 }
4364         } else {
4365                 r->devmode = NULL;
4366                 DEBUG(8,("Returning NULL Devicemode!\n"));
4367         }
4368
4369         compose_devicemode_devicename(r->devmode, printername);
4370
4371         return WERR_OK;
4372 }
4373
4374 /********************************************************************
4375  Spoolss_enumprinters.
4376 ********************************************************************/
4377
4378 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4379                                            const struct auth_session_info *session_info,
4380                                            struct messaging_context *msg_ctx,
4381                                            const char *servername,
4382                                            uint32_t level,
4383                                            uint32_t flags,
4384                                            union spoolss_PrinterInfo **info_p,
4385                                            uint32_t *count_p)
4386 {
4387         int snum;
4388         int n_services;
4389         union spoolss_PrinterInfo *info = NULL;
4390         uint32_t count = 0;
4391         WERROR result = WERR_OK;
4392         struct dcerpc_binding_handle *b = NULL;
4393         TALLOC_CTX *tmp_ctx = NULL;
4394
4395         tmp_ctx = talloc_new(mem_ctx);
4396         if (!tmp_ctx) {
4397                 return WERR_NOT_ENOUGH_MEMORY;
4398         }
4399
4400         /*
4401          * printer shares are updated on client enumeration. The background
4402          * printer process updates printer_list.tdb at regular intervals.
4403          */
4404         become_root();
4405         delete_and_reload_printers(server_event_context(), msg_ctx);
4406         unbecome_root();
4407
4408         n_services = lp_numservices();
4409         *count_p = 0;
4410         *info_p = NULL;
4411
4412         for (snum = 0; snum < n_services; snum++) {
4413
4414                 const char *printer;
4415                 struct spoolss_PrinterInfo2 *info2;
4416
4417                 if (!snum_is_shared_printer(snum)) {
4418                         continue;
4419                 }
4420
4421                 printer = lp_const_servicename(snum);
4422
4423                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4424                         printer, snum));
4425
4426                 if (b == NULL) {
4427                         result = winreg_printer_binding_handle(tmp_ctx,
4428                                                                session_info,
4429                                                                msg_ctx,
4430                                                                &b);
4431                         if (!W_ERROR_IS_OK(result)) {
4432                                 goto out;
4433                         }
4434                 }
4435
4436                 result = winreg_create_printer(tmp_ctx, b,
4437                                                printer);
4438                 if (!W_ERROR_IS_OK(result)) {
4439                         goto out;
4440                 }
4441
4442                 info = talloc_realloc(tmp_ctx, info,
4443                                             union spoolss_PrinterInfo,
4444                                             count + 1);
4445                 if (!info) {
4446                         result = WERR_NOT_ENOUGH_MEMORY;
4447                         goto out;
4448                 }
4449
4450                 result = winreg_get_printer(tmp_ctx, b,
4451                                             printer, &info2);
4452                 if (!W_ERROR_IS_OK(result)) {
4453                         goto out;
4454                 }
4455
4456                 switch (level) {
4457                 case 0:
4458                         result = construct_printer_info0(info, session_info,
4459                                                          msg_ctx, info2,
4460                                                          servername,
4461                                                          &info[count].info0, snum);
4462                         break;
4463                 case 1:
4464                         result = construct_printer_info1(info, info2, flags,
4465                                                          servername,
4466                                                          &info[count].info1, snum);
4467                         break;
4468                 case 2:
4469                         result = construct_printer_info2(info, msg_ctx, info2,
4470                                                          servername,
4471                                                          &info[count].info2, snum);
4472                         break;
4473                 case 4:
4474                         result = construct_printer_info4(info, info2,
4475                                                          servername,
4476                                                          &info[count].info4, snum);
4477                         break;
4478                 case 5:
4479                         result = construct_printer_info5(info, info2,
4480                                                          servername,
4481                                                          &info[count].info5, snum);
4482                         break;
4483
4484                 default:
4485                         result = WERR_INVALID_LEVEL;
4486                         goto out;
4487                 }
4488
4489                 if (!W_ERROR_IS_OK(result)) {
4490                         goto out;
4491                 }
4492
4493                 count++;
4494         }
4495
4496 out:
4497         if (W_ERROR_IS_OK(result)) {
4498                 *info_p = talloc_move(mem_ctx, &info);
4499                 *count_p = count;
4500         }
4501
4502         talloc_free(tmp_ctx);
4503
4504         return result;
4505 }
4506
4507 /********************************************************************
4508  * handle enumeration of printers at level 0
4509  ********************************************************************/
4510
4511 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4512                                   const struct auth_session_info *session_info,
4513                                   struct messaging_context *msg_ctx,
4514                                   uint32_t flags,
4515                                   const char *servername,
4516                                   union spoolss_PrinterInfo **info,
4517                                   uint32_t *count)
4518 {
4519         DEBUG(4,("enum_all_printers_info_0\n"));
4520
4521         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4522                                             servername, 0, flags, info, count);
4523 }
4524
4525
4526 /********************************************************************
4527 ********************************************************************/
4528
4529 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4530                                        const struct auth_session_info *session_info,
4531                                        struct messaging_context *msg_ctx,
4532                                        const char *servername,
4533                                        uint32_t flags,
4534                                        union spoolss_PrinterInfo **info,
4535                                        uint32_t *count)
4536 {
4537         DEBUG(4,("enum_all_printers_info_1\n"));
4538
4539         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4540                                             servername, 1, flags, info, count);
4541 }
4542
4543 /********************************************************************
4544  enum_all_printers_info_1_local.
4545 *********************************************************************/
4546
4547 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4548                                              const struct auth_session_info *session_info,
4549                                              struct messaging_context *msg_ctx,
4550                                              const char *servername,
4551                                              union spoolss_PrinterInfo **info,
4552                                              uint32_t *count)
4553 {
4554         DEBUG(4,("enum_all_printers_info_1_local\n"));
4555
4556         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4557                                         servername, PRINTER_ENUM_ICON8, info, count);
4558 }
4559
4560 /********************************************************************
4561  enum_all_printers_info_1_name.
4562 *********************************************************************/
4563
4564 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4565                                             const struct auth_session_info *session_info,
4566                                             struct messaging_context *msg_ctx,
4567                                             const char *servername,
4568                                             union spoolss_PrinterInfo **info,
4569                                             uint32_t *count)
4570 {
4571         const char *s = servername;
4572
4573         DEBUG(4,("enum_all_printers_info_1_name\n"));
4574
4575         if (servername != NULL &&
4576             (servername[0] == '\\') && (servername[1] == '\\')) {
4577                 s = servername + 2;
4578         }
4579
4580         if (!is_myname_or_ipaddr(s)) {
4581                 return WERR_INVALID_NAME;
4582         }
4583
4584         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4585                                         servername, PRINTER_ENUM_ICON8, info, count);
4586 }
4587
4588 /********************************************************************
4589  enum_all_printers_info_1_network.
4590 *********************************************************************/
4591
4592 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4593                                                const struct auth_session_info *session_info,
4594                                                struct messaging_context *msg_ctx,
4595                                                const char *servername,
4596                                                union spoolss_PrinterInfo **info,
4597                                                uint32_t *count)
4598 {
4599         const char *s = servername;
4600
4601         DEBUG(4,("enum_all_printers_info_1_network\n"));
4602
4603         /* If we respond to a enum_printers level 1 on our name with flags
4604            set to PRINTER_ENUM_REMOTE with a list of printers then these
4605            printers incorrectly appear in the APW browse list.
4606            Specifically the printers for the server appear at the workgroup
4607            level where all the other servers in the domain are
4608            listed. Windows responds to this call with a
4609            WERR_CAN_NOT_COMPLETE so we should do the same. */
4610
4611         if (servername != NULL &&
4612             (servername[0] == '\\') && (servername[1] == '\\')) {
4613                  s = servername + 2;
4614         }
4615
4616         if (is_myname_or_ipaddr(s)) {
4617                  return WERR_CAN_NOT_COMPLETE;
4618         }
4619
4620         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4621                                         servername, PRINTER_ENUM_NAME, info, count);
4622 }
4623
4624 /********************************************************************
4625  * api_spoolss_enumprinters
4626  *
4627  * called from api_spoolss_enumprinters (see this to understand)
4628  ********************************************************************/
4629
4630 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4631                                        const struct auth_session_info *session_info,
4632                                        struct messaging_context *msg_ctx,
4633                                        const char *servername,
4634                                        union spoolss_PrinterInfo **info,
4635                                        uint32_t *count)
4636 {
4637         DEBUG(4,("enum_all_printers_info_2\n"));
4638
4639         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4640                                             servername, 2, 0, info, count);
4641 }
4642
4643 /********************************************************************
4644  * handle enumeration of printers at level 1
4645  ********************************************************************/
4646
4647 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4648                                   const struct auth_session_info *session_info,
4649                                   struct messaging_context *msg_ctx,
4650                                   uint32_t flags,
4651                                   const char *servername,
4652                                   union spoolss_PrinterInfo **info,
4653                                   uint32_t *count)
4654 {
4655         /* Not all the flags are equals */
4656
4657         if (flags & PRINTER_ENUM_LOCAL) {
4658                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4659                                                       msg_ctx, servername, info, count);
4660         }
4661
4662         if (flags & PRINTER_ENUM_NAME) {
4663                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4664                                                      msg_ctx, servername, info,
4665                                                      count);
4666         }
4667
4668         if (flags & PRINTER_ENUM_NETWORK) {
4669                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4670                                                         msg_ctx, servername, info,
4671                                                         count);
4672         }
4673
4674         return WERR_OK; /* NT4sp5 does that */
4675 }
4676
4677 /********************************************************************
4678  * handle enumeration of printers at level 2
4679  ********************************************************************/
4680
4681 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4682                                   const struct auth_session_info *session_info,
4683                                   struct messaging_context *msg_ctx,
4684                                   uint32_t flags,
4685                                   const char *servername,
4686                                   union spoolss_PrinterInfo **info,
4687                                   uint32_t *count)
4688 {
4689         if (flags & PRINTER_ENUM_LOCAL) {
4690
4691                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4692                                                 servername,
4693                                                 info, count);
4694         }
4695
4696         if (flags & PRINTER_ENUM_NAME) {
4697                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4698                         return WERR_INVALID_NAME;
4699                 }
4700
4701                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4702                                                 servername,
4703                                                 info, count);
4704         }
4705
4706         if (flags & PRINTER_ENUM_REMOTE) {
4707                 return WERR_INVALID_LEVEL;
4708         }
4709
4710         return WERR_OK;
4711 }
4712
4713 /********************************************************************
4714  * handle enumeration of printers at level 4
4715  ********************************************************************/
4716
4717 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4718                                   const struct auth_session_info *session_info,
4719                                   struct messaging_context *msg_ctx,
4720                                   uint32_t flags,
4721                                   const char *servername,
4722                                   union spoolss_PrinterInfo **info,
4723                                   uint32_t *count)
4724 {
4725         DEBUG(4,("enum_all_printers_info_4\n"));
4726
4727         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4728                                             servername, 4, flags, info, count);
4729 }
4730
4731
4732 /********************************************************************
4733  * handle enumeration of printers at level 5
4734  ********************************************************************/
4735
4736 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4737                                   const struct auth_session_info *session_info,
4738                                   struct messaging_context *msg_ctx,
4739                                   uint32_t flags,
4740                                   const char *servername,
4741                                   union spoolss_PrinterInfo **info,
4742                                   uint32_t *count)
4743 {
4744         DEBUG(4,("enum_all_printers_info_5\n"));
4745
4746         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4747                                             servername, 5, flags, info, count);
4748 }
4749
4750 /****************************************************************
4751  _spoolss_EnumPrinters
4752 ****************************************************************/
4753
4754 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4755                              struct spoolss_EnumPrinters *r)
4756 {
4757         const struct auth_session_info *session_info = get_session_info_system();
4758         WERROR result;
4759
4760         /* that's an [in out] buffer */
4761
4762         if (!r->in.buffer && (r->in.offered != 0)) {
4763                 return WERR_INVALID_PARAMETER;
4764         }
4765
4766         DEBUG(4,("_spoolss_EnumPrinters\n"));
4767
4768         *r->out.needed = 0;
4769         *r->out.count = 0;
4770         *r->out.info = NULL;
4771
4772         /*
4773          * Level 1:
4774          *          flags==PRINTER_ENUM_NAME
4775          *           if name=="" then enumerates all printers
4776          *           if name!="" then enumerate the printer
4777          *          flags==PRINTER_ENUM_REMOTE
4778          *          name is NULL, enumerate printers
4779          * Level 2: name!="" enumerates printers, name can't be NULL
4780          * Level 3: doesn't exist
4781          * Level 4: does a local registry lookup
4782          * Level 5: same as Level 2
4783          */
4784
4785         if (r->in.server && r->in.server[0] == '\0') {
4786                 r->in.server = NULL;
4787         }
4788
4789         switch (r->in.level) {
4790         case 0:
4791                 result = enumprinters_level0(p->mem_ctx, session_info,
4792                                              p->msg_ctx, r->in.flags,
4793                                              r->in.server,
4794                                              r->out.info, r->out.count);
4795                 break;
4796         case 1:
4797                 result = enumprinters_level1(p->mem_ctx, session_info,
4798                                              p->msg_ctx, r->in.flags,
4799                                              r->in.server,
4800                                              r->out.info, r->out.count);
4801                 break;
4802         case 2:
4803                 result = enumprinters_level2(p->mem_ctx, session_info,
4804                                              p->msg_ctx, r->in.flags,
4805                                              r->in.server,
4806                                              r->out.info, r->out.count);
4807                 break;
4808         case 4:
4809                 result = enumprinters_level4(p->mem_ctx, session_info,
4810                                              p->msg_ctx, r->in.flags,
4811                                              r->in.server,
4812                                              r->out.info, r->out.count);
4813                 break;
4814         case 5:
4815                 result = enumprinters_level5(p->mem_ctx, session_info,
4816                                              p->msg_ctx, r->in.flags,
4817                                              r->in.server,
4818                                              r->out.info, r->out.count);
4819                 break;
4820         default:
4821                 return WERR_INVALID_LEVEL;
4822         }
4823
4824         if (!W_ERROR_IS_OK(result)) {
4825                 return result;
4826         }
4827
4828         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4829                                                      spoolss_EnumPrinters,
4830                                                      *r->out.info, r->in.level,
4831                                                      *r->out.count);
4832         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4833         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4834
4835         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4836 }
4837
4838 /****************************************************************
4839  _spoolss_GetPrinter
4840 ****************************************************************/
4841
4842 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4843                            struct spoolss_GetPrinter *r)
4844 {
4845         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4846         struct spoolss_PrinterInfo2 *info2 = NULL;
4847         WERROR result = WERR_OK;
4848         int snum;
4849
4850         /* that's an [in out] buffer */
4851
4852         if (!r->in.buffer && (r->in.offered != 0)) {
4853                 result = WERR_INVALID_PARAMETER;
4854                 goto err_info_free;
4855         }
4856
4857         *r->out.needed = 0;
4858
4859         if (Printer == NULL) {
4860                 result = WERR_INVALID_HANDLE;
4861                 goto err_info_free;
4862         }
4863
4864         if (Printer->printer_type == SPLHND_SERVER) {
4865
4866                 struct dcerpc_binding_handle *b;
4867
4868                 if (r->in.level != 3) {
4869                         result = WERR_INVALID_LEVEL;
4870                         goto err_info_free;
4871                 }
4872
4873                 result = winreg_printer_binding_handle(p->mem_ctx,
4874                                                        get_session_info_system(),
4875                                                        p->msg_ctx,
4876                                                        &b);
4877                 if (!W_ERROR_IS_OK(result)) {
4878                         goto err_info_free;
4879                 }
4880
4881                 result = winreg_get_printserver_secdesc(p->mem_ctx,
4882                                                         b,
4883                                                         &r->out.info->info3.secdesc);
4884                 if (!W_ERROR_IS_OK(result)) {
4885                         goto err_info_free;
4886                 }
4887
4888                 goto done;
4889         }
4890
4891         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4892                 result = WERR_INVALID_HANDLE;
4893                 goto err_info_free;
4894         }
4895
4896         result = winreg_get_printer_internal(p->mem_ctx,
4897                                     get_session_info_system(),
4898                                     p->msg_ctx,
4899                                     lp_const_servicename(snum),
4900                                     &info2);
4901         if (!W_ERROR_IS_OK(result)) {
4902                 goto err_info_free;
4903         }
4904
4905         switch (r->in.level) {
4906         case 0:
4907                 result = construct_printer_info0(p->mem_ctx,
4908                                                  get_session_info_system(),
4909                                                  p->msg_ctx,
4910                                                  info2,
4911                                                  Printer->servername,
4912                                                  &r->out.info->info0,
4913                                                  snum);
4914                 break;
4915         case 1:
4916                 result = construct_printer_info1(p->mem_ctx, info2,
4917                                                  PRINTER_ENUM_ICON8,
4918                                                  Printer->servername,
4919                                                  &r->out.info->info1, snum);
4920                 break;
4921         case 2:
4922                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4923                                                  Printer->servername,
4924                                                  &r->out.info->info2, snum);
4925                 break;
4926         case 3:
4927                 result = construct_printer_info3(p->mem_ctx, info2,
4928                                                  Printer->servername,
4929                                                  &r->out.info->info3, snum);
4930                 break;
4931         case 4:
4932                 result = construct_printer_info4(p->mem_ctx, info2,
4933                                                  Printer->servername,
4934                                                  &r->out.info->info4, snum);
4935                 break;
4936         case 5:
4937                 result = construct_printer_info5(p->mem_ctx, info2,
4938                                                  Printer->servername,
4939                                                  &r->out.info->info5, snum);
4940                 break;
4941         case 6:
4942                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4943                                                  Printer->servername,
4944                                                  &r->out.info->info6, snum);
4945                 break;
4946         case 7:
4947                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4948                                                  Printer->servername,
4949                                                  &r->out.info->info7, snum);
4950                 break;
4951         case 8:
4952                 result = construct_printer_info8(p->mem_ctx, info2,
4953                                                  Printer->servername,
4954                                                  &r->out.info->info8, snum);
4955                 break;
4956         default:
4957                 result = WERR_INVALID_LEVEL;
4958                 break;
4959         }
4960         TALLOC_FREE(info2);
4961
4962         if (!W_ERROR_IS_OK(result)) {
4963                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4964                           r->in.level, win_errstr(result)));
4965                 goto err_info_free;
4966         }
4967  done:
4968         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4969                                                r->out.info, r->in.level);
4970         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4971
4972         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4973
4974 err_info_free:
4975         TALLOC_FREE(r->out.info);
4976         return result;
4977 }
4978
4979 /********************************************************************
4980  ********************************************************************/
4981
4982 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4983         do { \
4984                 if (in && strlen(in)) { \
4985                         out = talloc_strdup(mem_ctx, in); \
4986                 } else { \
4987                         out = talloc_strdup(mem_ctx, ""); \
4988                 } \
4989                 W_ERROR_HAVE_NO_MEMORY(out); \
4990         } while (0);
4991
4992 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4993         do { \
4994                 if (in && strlen(in)) { \
4995                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4996                 } else { \
4997                         out = talloc_strdup(mem_ctx, ""); \
4998                 } \
4999                 W_ERROR_HAVE_NO_MEMORY(out); \
5000         } while (0);
5001
5002 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
5003                                                   const char **string_array,
5004                                                   const char ***presult,
5005                                                   const char *cservername,
5006                                                   const char *arch,
5007                                                   int version)
5008 {
5009         size_t i;
5010         size_t num_strings = 0;
5011         const char **array = NULL;
5012
5013         if (string_array == NULL) {
5014                 return WERR_INVALID_PARAMETER;
5015         }
5016
5017         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
5018                 const char *str = NULL;
5019
5020                 if (cservername == NULL || arch == NULL) {
5021                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
5022                 } else {
5023                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
5024                 }
5025
5026                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5027                         TALLOC_FREE(array);
5028                         return WERR_NOT_ENOUGH_MEMORY;
5029                 }
5030         }
5031
5032         if (i > 0) {
5033                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5034                              &array, &num_strings);
5035         }
5036
5037         if (presult != NULL) {
5038                 *presult = array;
5039         } else {
5040                 talloc_free(array);
5041         }
5042
5043         return WERR_OK;
5044 }
5045
5046 /********************************************************************
5047  * fill a spoolss_DriverInfo1 struct
5048  ********************************************************************/
5049
5050 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5051                                         struct spoolss_DriverInfo1 *r,
5052                                         const struct spoolss_DriverInfo8 *driver,
5053                                         const char *servername)
5054 {
5055         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5056         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5057
5058         return WERR_OK;
5059 }
5060
5061 /********************************************************************
5062  * fill a spoolss_DriverInfo2 struct
5063  ********************************************************************/
5064
5065 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5066                                         struct spoolss_DriverInfo2 *r,
5067                                         const struct spoolss_DriverInfo8 *driver,
5068                                         const char *servername)
5069
5070 {
5071         const char *cservername = canon_servername(servername);
5072
5073         r->version              = driver->version;
5074
5075         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5076         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5077         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5078         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5079
5080         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5081                                driver->architecture,
5082                                driver->version,
5083                                driver->driver_path,
5084                                r->driver_path);
5085
5086         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5087                                driver->architecture,
5088                                driver->version,
5089                                driver->data_file,
5090                                r->data_file);
5091
5092         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5093                                driver->architecture,
5094                                driver->version,
5095                                driver->config_file,
5096                                r->config_file);
5097
5098         return WERR_OK;
5099 }
5100
5101 /********************************************************************
5102  * fill a spoolss_DriverInfo3 struct
5103  ********************************************************************/
5104
5105 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5106                                         struct spoolss_DriverInfo3 *r,
5107                                         const struct spoolss_DriverInfo8 *driver,
5108                                         const char *servername)
5109 {
5110         const char *cservername = canon_servername(servername);
5111
5112         r->version              = driver->version;
5113
5114         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5115         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5116         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5117         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5118
5119         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5120                                driver->architecture,
5121                                driver->version,
5122                                driver->driver_path,
5123                                r->driver_path);
5124
5125         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5126                                driver->architecture,
5127                                driver->version,
5128                                driver->data_file,
5129                                r->data_file);
5130
5131         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5132                                driver->architecture,
5133                                driver->version,
5134                                driver->config_file,
5135                                r->config_file);
5136
5137         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5138                                driver->architecture,
5139                                driver->version,
5140                                driver->help_file,
5141                                r->help_file);
5142
5143         FILL_DRIVER_STRING(mem_ctx,
5144                            driver->monitor_name,
5145                            r->monitor_name);
5146
5147         FILL_DRIVER_STRING(mem_ctx,
5148                            driver->default_datatype,
5149                            r->default_datatype);
5150
5151         return string_array_from_driver_info(mem_ctx,
5152                                              driver->dependent_files,
5153                                              &r->dependent_files,
5154                                              cservername,
5155                                              driver->architecture,
5156                                              driver->version);
5157 }
5158
5159 /********************************************************************
5160  * fill a spoolss_DriverInfo4 struct
5161  ********************************************************************/
5162
5163 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5164                                         struct spoolss_DriverInfo4 *r,
5165                                         const struct spoolss_DriverInfo8 *driver,
5166                                         const char *servername)
5167 {
5168         const char *cservername = canon_servername(servername);
5169         WERROR result;
5170
5171         r->version              = driver->version;
5172
5173         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5174         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5175         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5176         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5177
5178         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5179                                driver->architecture,
5180                                driver->version,
5181                                driver->driver_path,
5182                                r->driver_path);
5183
5184         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5185                                driver->architecture,
5186                                driver->version,
5187                                driver->data_file,
5188                                r->data_file);
5189
5190         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5191                                driver->architecture,
5192                                driver->version,
5193                                driver->config_file,
5194                                r->config_file);
5195
5196         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5197                                driver->architecture,
5198                                driver->version,
5199                                driver->help_file,
5200                                r->help_file);
5201
5202         result = string_array_from_driver_info(mem_ctx,
5203                                                driver->dependent_files,
5204                                                &r->dependent_files,
5205                                                cservername,
5206                                                driver->architecture,
5207                                                driver->version);
5208         if (!W_ERROR_IS_OK(result)) {
5209                 return result;
5210         }
5211
5212         FILL_DRIVER_STRING(mem_ctx,
5213                            driver->monitor_name,
5214                            r->monitor_name);
5215
5216         FILL_DRIVER_STRING(mem_ctx,
5217                            driver->default_datatype,
5218                            r->default_datatype);
5219
5220
5221         result = string_array_from_driver_info(mem_ctx,
5222                                                driver->previous_names,
5223                                                &r->previous_names,
5224                                                NULL, NULL, 0);
5225
5226         return result;
5227 }
5228
5229 /********************************************************************
5230  * fill a spoolss_DriverInfo5 struct
5231  ********************************************************************/
5232
5233 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5234                                         struct spoolss_DriverInfo5 *r,
5235                                         const struct spoolss_DriverInfo8 *driver,
5236                                         const char *servername)
5237 {
5238         const char *cservername = canon_servername(servername);
5239
5240         r->version              = driver->version;
5241
5242         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5243         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5244         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5245         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5246
5247         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5248                                driver->architecture,
5249                                driver->version,
5250                                driver->driver_path,
5251                                r->driver_path);
5252
5253         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5254                                driver->architecture,
5255                                driver->version,
5256                                driver->data_file,
5257                                r->data_file);
5258
5259         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5260                                driver->architecture,
5261                                driver->version,
5262                                driver->config_file,
5263                                r->config_file);
5264
5265         r->driver_attributes    = 0;
5266         r->config_version       = 0;
5267         r->driver_version       = 0;
5268
5269         return WERR_OK;
5270 }
5271 /********************************************************************
5272  * fill a spoolss_DriverInfo6 struct
5273  ********************************************************************/
5274
5275 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5276                                         struct spoolss_DriverInfo6 *r,
5277                                         const struct spoolss_DriverInfo8 *driver,
5278                                         const char *servername)
5279 {
5280         const char *cservername = canon_servername(servername);
5281         WERROR result;
5282
5283         r->version              = driver->version;
5284
5285         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5286         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5287         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5288         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5289
5290         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5291                                driver->architecture,
5292                                driver->version,
5293                                driver->driver_path,
5294                                r->driver_path);
5295
5296         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5297                                driver->architecture,
5298                                driver->version,
5299                                driver->data_file,
5300                                r->data_file);
5301
5302         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5303                                driver->architecture,
5304                                driver->version,
5305                                driver->config_file,
5306                                r->config_file);
5307
5308         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5309                                driver->architecture,
5310                                driver->version,
5311                                driver->help_file,
5312                                r->help_file);
5313
5314         FILL_DRIVER_STRING(mem_ctx,
5315                            driver->monitor_name,
5316                            r->monitor_name);
5317
5318         FILL_DRIVER_STRING(mem_ctx,
5319                            driver->default_datatype,
5320                            r->default_datatype);
5321
5322         result = string_array_from_driver_info(mem_ctx,
5323                                                driver->dependent_files,
5324                                                &r->dependent_files,
5325                                                cservername,
5326                                                driver->architecture,
5327                                                driver->version);
5328         if (!W_ERROR_IS_OK(result)) {
5329                 return result;
5330         }
5331
5332         result = string_array_from_driver_info(mem_ctx,
5333                                                driver->previous_names,
5334                                                &r->previous_names,
5335                                                NULL, NULL, 0);
5336         if (!W_ERROR_IS_OK(result)) {
5337                 return result;
5338         }
5339
5340         r->driver_date          = driver->driver_date;
5341         r->driver_version       = driver->driver_version;
5342
5343         FILL_DRIVER_STRING(mem_ctx,
5344                            driver->manufacturer_name,
5345                            r->manufacturer_name);
5346         FILL_DRIVER_STRING(mem_ctx,
5347                            driver->manufacturer_url,
5348                            r->manufacturer_url);
5349         FILL_DRIVER_STRING(mem_ctx,
5350                            driver->hardware_id,
5351                            r->hardware_id);
5352         FILL_DRIVER_STRING(mem_ctx,
5353                            driver->provider,
5354                            r->provider);
5355
5356         return WERR_OK;
5357 }
5358
5359 /********************************************************************
5360  * fill a spoolss_DriverInfo8 struct
5361  ********************************************************************/
5362
5363 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5364                                         struct spoolss_DriverInfo8 *r,
5365                                         const struct spoolss_DriverInfo8 *driver,
5366                                         const char *servername)
5367 {
5368         const char *cservername = canon_servername(servername);
5369         WERROR result;
5370
5371         r->version              = driver->version;
5372
5373         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5374         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5375         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5376         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5377
5378         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5379                                driver->architecture,
5380                                driver->version,
5381                                driver->driver_path,
5382                                r->driver_path);
5383
5384         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5385                                driver->architecture,
5386                                driver->version,
5387                                driver->data_file,
5388                                r->data_file);
5389
5390         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5391                                driver->architecture,
5392                                driver->version,
5393                                driver->config_file,
5394                                r->config_file);
5395
5396         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5397                                driver->architecture,
5398                                driver->version,
5399                                driver->help_file,
5400                                r->help_file);
5401
5402         FILL_DRIVER_STRING(mem_ctx,
5403                            driver->monitor_name,
5404                            r->monitor_name);
5405
5406         FILL_DRIVER_STRING(mem_ctx,
5407                            driver->default_datatype,
5408                            r->default_datatype);
5409
5410         result = string_array_from_driver_info(mem_ctx,
5411                                                driver->dependent_files,
5412                                                &r->dependent_files,
5413                                                cservername,
5414                                                driver->architecture,
5415                                                driver->version);
5416         if (!W_ERROR_IS_OK(result)) {
5417                 return result;
5418         }
5419
5420         result = string_array_from_driver_info(mem_ctx,
5421                                                driver->previous_names,
5422                                                &r->previous_names,
5423                                                NULL, NULL, 0);
5424         if (!W_ERROR_IS_OK(result)) {
5425                 return result;
5426         }
5427
5428         r->driver_date          = driver->driver_date;
5429         r->driver_version       = driver->driver_version;
5430
5431         FILL_DRIVER_STRING(mem_ctx,
5432                            driver->manufacturer_name,
5433                            r->manufacturer_name);
5434         FILL_DRIVER_STRING(mem_ctx,
5435                            driver->manufacturer_url,
5436                            r->manufacturer_url);
5437         FILL_DRIVER_STRING(mem_ctx,
5438                            driver->hardware_id,
5439                            r->hardware_id);
5440         FILL_DRIVER_STRING(mem_ctx,
5441                            driver->provider,
5442                            r->provider);
5443
5444         FILL_DRIVER_STRING(mem_ctx,
5445                            driver->print_processor,
5446                            r->print_processor);
5447         FILL_DRIVER_STRING(mem_ctx,
5448                            driver->vendor_setup,
5449                            r->vendor_setup);
5450
5451         result = string_array_from_driver_info(mem_ctx,
5452                                                driver->color_profiles,
5453                                                &r->color_profiles,
5454                                                NULL, NULL, 0);
5455         if (!W_ERROR_IS_OK(result)) {
5456                 return result;
5457         }
5458
5459         FILL_DRIVER_STRING(mem_ctx,
5460                            driver->inf_path,
5461                            r->inf_path);
5462
5463         r->printer_driver_attributes    = driver->printer_driver_attributes;
5464
5465         result = string_array_from_driver_info(mem_ctx,
5466                                                driver->core_driver_dependencies,
5467                                                &r->core_driver_dependencies,
5468                                                NULL, NULL, 0);
5469         if (!W_ERROR_IS_OK(result)) {
5470                 return result;
5471         }
5472
5473         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5474         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5475
5476         return WERR_OK;
5477 }
5478
5479 #if 0 /* disabled until marshalling issues are resolved - gd */
5480 /********************************************************************
5481  ********************************************************************/
5482
5483 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5484                                           struct spoolss_DriverFileInfo *r,
5485                                           const char *cservername,
5486                                           const char *file_name,
5487                                           enum spoolss_DriverFileType file_type,
5488                                           uint32_t file_version)
5489 {
5490         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5491                                           cservername, file_name);
5492         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5493         r->file_type    = file_type;
5494         r->file_version = file_version;
5495
5496         return WERR_OK;
5497 }
5498
5499 /********************************************************************
5500  ********************************************************************/
5501
5502 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5503                                                  const struct spoolss_DriverInfo8 *driver,
5504                                                  const char *cservername,
5505                                                  struct spoolss_DriverFileInfo **info_p,
5506                                                  uint32_t *count_p)
5507 {
5508         struct spoolss_DriverFileInfo *info = NULL;
5509         uint32_t count = 0;
5510         WERROR result;
5511         uint32_t i;
5512
5513         *info_p = NULL;
5514         *count_p = 0;
5515
5516         if (strlen(driver->driver_path)) {
5517                 info = talloc_realloc(mem_ctx, info,
5518                                             struct spoolss_DriverFileInfo,
5519                                             count + 1);
5520                 W_ERROR_HAVE_NO_MEMORY(info);
5521                 result = fill_spoolss_DriverFileInfo(info,
5522                                                      &info[count],
5523                                                      cservername,
5524                                                      driver->driver_path,
5525                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5526                                                      0);
5527                 W_ERROR_NOT_OK_RETURN(result);
5528                 count++;
5529         }
5530
5531         if (strlen(driver->config_file)) {
5532                 info = talloc_realloc(mem_ctx, info,
5533                                             struct spoolss_DriverFileInfo,
5534                                             count + 1);
5535                 W_ERROR_HAVE_NO_MEMORY(info);
5536                 result = fill_spoolss_DriverFileInfo(info,
5537                                                      &info[count],
5538                                                      cservername,
5539                                                      driver->config_file,
5540                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5541                                                      0);
5542                 W_ERROR_NOT_OK_RETURN(result);
5543                 count++;
5544         }
5545
5546         if (strlen(driver->data_file)) {
5547                 info = talloc_realloc(mem_ctx, info,
5548                                             struct spoolss_DriverFileInfo,
5549                                             count + 1);
5550                 W_ERROR_HAVE_NO_MEMORY(info);
5551                 result = fill_spoolss_DriverFileInfo(info,
5552                                                      &info[count],
5553                                                      cservername,
5554                                                      driver->data_file,
5555                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5556                                                      0);
5557                 W_ERROR_NOT_OK_RETURN(result);
5558                 count++;
5559         }
5560
5561         if (strlen(driver->help_file)) {
5562                 info = talloc_realloc(mem_ctx, info,
5563                                             struct spoolss_DriverFileInfo,
5564                                             count + 1);
5565                 W_ERROR_HAVE_NO_MEMORY(info);
5566                 result = fill_spoolss_DriverFileInfo(info,
5567                                                      &info[count],
5568                                                      cservername,
5569                                                      driver->help_file,
5570                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5571                                                      0);
5572                 W_ERROR_NOT_OK_RETURN(result);
5573                 count++;
5574         }
5575
5576         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5577                 info = talloc_realloc(mem_ctx, info,
5578                                             struct spoolss_DriverFileInfo,
5579                                             count + 1);
5580                 W_ERROR_HAVE_NO_MEMORY(info);
5581                 result = fill_spoolss_DriverFileInfo(info,
5582                                                      &info[count],
5583                                                      cservername,
5584                                                      driver->dependent_files[i],
5585                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5586                                                      0);
5587                 W_ERROR_NOT_OK_RETURN(result);
5588                 count++;
5589         }
5590
5591         *info_p = info;
5592         *count_p = count;
5593
5594         return WERR_OK;
5595 }
5596
5597 /********************************************************************
5598  * fill a spoolss_DriverInfo101 struct
5599  ********************************************************************/
5600
5601 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5602                                           struct spoolss_DriverInfo101 *r,
5603                                           const struct spoolss_DriverInfo8 *driver,
5604                                           const char *servername)
5605 {
5606         const char *cservername = canon_servername(servername);
5607         WERROR result;
5608
5609         r->version              = driver->version;
5610
5611         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5612         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5613         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5614         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5615
5616         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5617                                                     cservername,
5618                                                     &r->file_info,
5619                                                     &r->file_count);
5620         if (!W_ERROR_IS_OK(result)) {
5621                 return result;
5622         }
5623
5624         FILL_DRIVER_STRING(mem_ctx,
5625                            driver->monitor_name,
5626                            r->monitor_name);
5627
5628         FILL_DRIVER_STRING(mem_ctx,
5629                            driver->default_datatype,
5630                            r->default_datatype);
5631
5632         result = string_array_from_driver_info(mem_ctx,
5633                                                driver->previous_names,
5634                                                &r->previous_names,
5635                                                NULL, NULL, 0);
5636         if (!W_ERROR_IS_OK(result)) {
5637                 return result;
5638         }
5639
5640         r->driver_date          = driver->driver_date;
5641         r->driver_version       = driver->driver_version;
5642
5643         FILL_DRIVER_STRING(mem_ctx,
5644                            driver->manufacturer_name,
5645                            r->manufacturer_name);
5646         FILL_DRIVER_STRING(mem_ctx,
5647                            driver->manufacturer_url,
5648                            r->manufacturer_url);
5649         FILL_DRIVER_STRING(mem_ctx,
5650                            driver->hardware_id,
5651                            r->hardware_id);
5652         FILL_DRIVER_STRING(mem_ctx,
5653                            driver->provider,
5654                            r->provider);
5655
5656         return WERR_OK;
5657 }
5658 #endif
5659 /********************************************************************
5660  ********************************************************************/
5661
5662 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5663                                                   const struct auth_session_info *session_info,
5664                                                   struct messaging_context *msg_ctx,
5665                                                   uint32_t level,
5666                                                   union spoolss_DriverInfo *r,
5667                                                   int snum,
5668                                                   const char *servername,
5669                                                   const char *architecture,
5670                                                   uint32_t version)
5671 {
5672         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5673         struct spoolss_DriverInfo8 *driver;
5674         WERROR result;
5675         struct dcerpc_binding_handle *b;
5676         TALLOC_CTX *tmp_ctx = NULL;
5677
5678         if (level == 101) {
5679                 return WERR_INVALID_LEVEL;
5680         }
5681
5682         tmp_ctx = talloc_new(mem_ctx);
5683         if (!tmp_ctx) {
5684                 return WERR_NOT_ENOUGH_MEMORY;
5685         }
5686
5687         result = winreg_printer_binding_handle(tmp_ctx,
5688                                                session_info,
5689                                                msg_ctx,
5690                                                &b);
5691         if (!W_ERROR_IS_OK(result)) {
5692                 goto done;
5693         }
5694
5695         result = winreg_get_printer(tmp_ctx, b,
5696                                     lp_const_servicename(snum),
5697                                     &pinfo2);
5698         if (!W_ERROR_IS_OK(result)) {
5699                 DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
5700                         lp_const_servicename(snum), win_errstr(result));
5701                 result = WERR_INVALID_PRINTER_NAME;
5702                 goto done;
5703         }
5704
5705         if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
5706                 return WERR_UNKNOWN_PRINTER_DRIVER;
5707         }
5708
5709         DBG_INFO("Construct printer driver [%s] for [%s]\n",
5710                  pinfo2->drivername,
5711                  pinfo2->sharename);
5712
5713         result = winreg_get_driver(tmp_ctx, b,
5714                                    architecture,
5715                                    pinfo2->drivername, version, &driver);
5716
5717         DBG_INFO("winreg_get_driver() status: %s\n",
5718                  win_errstr(result));
5719
5720         if (!W_ERROR_IS_OK(result)) {
5721                 /*
5722                  * Is this a W2k client ?
5723                  */
5724
5725                 if (version < 3) {
5726                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5727                         goto done;
5728                 }
5729
5730                 /* Yes - try again with a WinNT driver. */
5731                 version = 2;
5732                 result = winreg_get_driver(tmp_ctx, b,
5733                                            architecture,
5734                                            pinfo2->drivername,
5735                                            version, &driver);
5736                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5737                         win_errstr(result)));
5738                 if (!W_ERROR_IS_OK(result)) {
5739                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5740                         goto done;
5741                 }
5742         }
5743
5744         /* these are allocated on mem_ctx and not tmp_ctx because they are
5745          * the 'return value' and need to utlive this call */
5746         switch (level) {
5747         case 1:
5748                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5749                 break;
5750         case 2:
5751                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5752                 break;
5753         case 3:
5754                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5755                 break;
5756         case 4:
5757                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5758                 break;
5759         case 5:
5760                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5761                 break;
5762         case 6:
5763                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5764                 break;
5765         case 8:
5766                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5767                 break;
5768 #if 0 /* disabled until marshalling issues are resolved - gd */
5769         case 101:
5770                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5771                 break;
5772 #endif
5773         default:
5774                 result = WERR_INVALID_LEVEL;
5775                 break;
5776         }
5777
5778 done:
5779         talloc_free(tmp_ctx);
5780         return result;
5781 }
5782
5783 /****************************************************************
5784  _spoolss_GetPrinterDriver2
5785 ****************************************************************/
5786
5787 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5788                                   struct spoolss_GetPrinterDriver2 *r)
5789 {
5790         struct printer_handle *printer;
5791         WERROR result;
5792         uint32_t version = r->in.client_major_version;
5793
5794         int snum;
5795
5796         /* that's an [in out] buffer */
5797
5798         if (!r->in.buffer && (r->in.offered != 0)) {
5799                 result = WERR_INVALID_PARAMETER;
5800                 goto err_info_free;
5801         }
5802
5803         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5804
5805         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5806                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5807                 result = WERR_INVALID_PRINTER_NAME;
5808                 goto err_info_free;
5809         }
5810
5811         *r->out.needed = 0;
5812         *r->out.server_major_version = 0;
5813         *r->out.server_minor_version = 0;
5814
5815         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5816                 result = WERR_INVALID_HANDLE;
5817                 goto err_info_free;
5818         }
5819
5820         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5821                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5822                         "downgrading to v3\n"));
5823                 version = SPOOLSS_DRIVER_VERSION_200X;
5824         }
5825
5826         result = construct_printer_driver_info_level(p->mem_ctx,
5827                                                      get_session_info_system(),
5828                                                      p->msg_ctx,
5829                                                      r->in.level, r->out.info,
5830                                                      snum, printer->servername,
5831                                                      r->in.architecture,
5832                                                      version);
5833         if (!W_ERROR_IS_OK(result)) {
5834                 goto err_info_free;
5835         }
5836
5837         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5838                                                r->out.info, r->in.level);
5839         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5840
5841         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5842
5843 err_info_free:
5844         TALLOC_FREE(r->out.info);
5845         return result;
5846 }
5847
5848
5849 /****************************************************************
5850  _spoolss_StartPagePrinter
5851 ****************************************************************/
5852
5853 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5854                                  struct spoolss_StartPagePrinter *r)
5855 {
5856         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5857
5858         if (!Printer) {
5859                 DEBUG(3,("_spoolss_StartPagePrinter: "
5860                         "Error in startpageprinter printer handle\n"));
5861                 return WERR_INVALID_HANDLE;
5862         }
5863
5864         Printer->page_started = true;
5865         return WERR_OK;
5866 }
5867
5868 /****************************************************************
5869  _spoolss_EndPagePrinter
5870 ****************************************************************/
5871
5872 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5873                                struct spoolss_EndPagePrinter *r)
5874 {
5875         int snum;
5876
5877         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5878
5879         if (!Printer) {
5880                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5881                         OUR_HANDLE(r->in.handle)));
5882                 return WERR_INVALID_HANDLE;
5883         }
5884
5885         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5886                 return WERR_INVALID_HANDLE;
5887
5888         Printer->page_started = false;
5889         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5890
5891         return WERR_OK;
5892 }
5893
5894 /****************************************************************
5895  _spoolss_StartDocPrinter
5896 ****************************************************************/
5897
5898 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5899                                 struct spoolss_StartDocPrinter *r)
5900 {
5901         struct spoolss_DocumentInfo1 *info_1;
5902         int snum;
5903         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5904         WERROR werr;
5905         char *rhost;
5906         int rc;
5907
5908         if (!Printer) {
5909                 DEBUG(2,("_spoolss_StartDocPrinter: "
5910                         "Invalid handle (%s:%u:%u)\n",
5911                         OUR_HANDLE(r->in.handle)));
5912                 return WERR_INVALID_HANDLE;
5913         }
5914
5915         if (Printer->jobid) {
5916                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5917                           "StartDocPrinter called twice! "
5918                           "(existing jobid = %d)\n", Printer->jobid));
5919                 return WERR_INVALID_HANDLE;
5920         }
5921
5922         if (r->in.info_ctr->level != 1) {
5923                 return WERR_INVALID_LEVEL;
5924         }
5925
5926         info_1 = r->in.info_ctr->info.info1;
5927
5928         /*
5929          * a nice thing with NT is it doesn't listen to what you tell it.
5930          * when asked to send _only_ RAW datas, it tries to send datas
5931          * in EMF format.
5932          *
5933          * So I add checks like in NT Server ...
5934          */
5935
5936         if (info_1->datatype) {
5937                 /*
5938                  * The v4 driver model used in Windows 8 declares print jobs
5939                  * intended to bypass the XPS processing layer by setting
5940                  * datatype to "XPS_PASS" instead of "RAW".
5941                  */
5942                 if ((strcmp(info_1->datatype, "RAW") != 0)
5943                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5944                         *r->out.job_id = 0;
5945                         return WERR_INVALID_DATATYPE;
5946                 }
5947         }
5948
5949         /* get the share number of the printer */
5950         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5951                 return WERR_INVALID_HANDLE;
5952         }
5953
5954         rc = get_remote_hostname(p->remote_address,
5955                                  &rhost,
5956                                  p->mem_ctx);
5957         if (rc < 0) {
5958                 return WERR_NOT_ENOUGH_MEMORY;
5959         }
5960         if (strequal(rhost,"UNKNOWN")) {
5961                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5962                                                          p->mem_ctx);
5963                 if (rhost == NULL) {
5964                         return WERR_NOT_ENOUGH_MEMORY;
5965                 }
5966         }
5967
5968         werr = print_job_start(p->session_info,
5969                                p->msg_ctx,
5970                                rhost,
5971                                snum,
5972                                info_1->document_name,
5973                                info_1->output_file,
5974                                Printer->devmode,
5975                                &Printer->jobid);
5976
5977         /* An error occurred in print_job_start() so return an appropriate
5978            NT error code. */
5979
5980         if (!W_ERROR_IS_OK(werr)) {
5981                 return werr;
5982         }
5983
5984         Printer->document_started = true;
5985         *r->out.job_id = Printer->jobid;
5986
5987         return WERR_OK;
5988 }
5989
5990 /****************************************************************
5991  _spoolss_EndDocPrinter
5992 ****************************************************************/
5993
5994 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5995                               struct spoolss_EndDocPrinter *r)
5996 {
5997         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5998         NTSTATUS status;
5999         int snum;
6000
6001         if (!Printer) {
6002                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
6003                         OUR_HANDLE(r->in.handle)));
6004                 return WERR_INVALID_HANDLE;
6005         }
6006
6007         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6008                 return WERR_INVALID_HANDLE;
6009         }
6010
6011         Printer->document_started = false;
6012         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
6013         if (!NT_STATUS_IS_OK(status)) {
6014                 DEBUG(2, ("_spoolss_EndDocPrinter: "
6015                           "print_job_end failed [%s]\n",
6016                           nt_errstr(status)));
6017         }
6018
6019         Printer->jobid = 0;
6020         return ntstatus_to_werror(status);
6021 }
6022
6023 /****************************************************************
6024  _spoolss_WritePrinter
6025 ****************************************************************/
6026
6027 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
6028                              struct spoolss_WritePrinter *r)
6029 {
6030         ssize_t buffer_written;
6031         int snum;
6032         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6033
6034         if (!Printer) {
6035                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6036                         OUR_HANDLE(r->in.handle)));
6037                 *r->out.num_written = r->in._data_size;
6038                 return WERR_INVALID_HANDLE;
6039         }
6040
6041         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6042                 return WERR_INVALID_HANDLE;
6043
6044         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
6045         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
6046                                                    snum, Printer->jobid,
6047                                                    (const char *)r->in.data.data,
6048                                                    (size_t)r->in._data_size);
6049         if (buffer_written == (ssize_t)-1) {
6050                 *r->out.num_written = 0;
6051                 if (errno == ENOSPC)
6052                         return WERR_NO_SPOOL_SPACE;
6053                 else
6054                         return WERR_ACCESS_DENIED;
6055         }
6056
6057         *r->out.num_written = r->in._data_size;
6058
6059         return WERR_OK;
6060 }
6061
6062 /********************************************************************
6063  * api_spoolss_getprinter
6064  * called from the spoolss dispatcher
6065  *
6066  ********************************************************************/
6067
6068 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6069                               struct pipes_struct *p)
6070 {
6071         const struct auth_session_info *session_info = p->session_info;
6072         int snum;
6073         WERROR errcode = WERR_INVALID_FUNCTION;
6074         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6075
6076         if (!Printer) {
6077                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6078                         OUR_HANDLE(handle)));
6079                 return WERR_INVALID_HANDLE;
6080         }
6081
6082         if (!get_printer_snum(p, handle, &snum, NULL))
6083                 return WERR_INVALID_HANDLE;
6084
6085         switch (command) {
6086         case SPOOLSS_PRINTER_CONTROL_PAUSE:
6087                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6088                 break;
6089         case SPOOLSS_PRINTER_CONTROL_RESUME:
6090         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6091                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6092                 break;
6093         case SPOOLSS_PRINTER_CONTROL_PURGE:
6094                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6095                 break;
6096         default:
6097                 return WERR_INVALID_LEVEL;
6098         }
6099
6100         return errcode;
6101 }
6102
6103
6104 /****************************************************************
6105  _spoolss_AbortPrinter
6106  * From MSDN: "Deletes printer's spool file if printer is configured
6107  * for spooling"
6108 ****************************************************************/
6109
6110 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6111                              struct spoolss_AbortPrinter *r)
6112 {
6113         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
6114         int             snum;
6115         WERROR          errcode = WERR_OK;
6116
6117         if (!Printer) {
6118                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6119                         OUR_HANDLE(r->in.handle)));
6120                 return WERR_INVALID_HANDLE;
6121         }
6122
6123         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6124                 return WERR_INVALID_HANDLE;
6125
6126         if (!Printer->document_started) {
6127                 return WERR_SPL_NO_STARTDOC;
6128         }
6129
6130         errcode = print_job_delete(p->session_info,
6131                                    p->msg_ctx,
6132                                    snum,
6133                                    Printer->jobid);
6134
6135         return errcode;
6136 }
6137
6138 /********************************************************************
6139  * called by spoolss_api_setprinter
6140  * when updating a printer description
6141  ********************************************************************/
6142
6143 static WERROR update_printer_sec(struct policy_handle *handle,
6144                                  struct pipes_struct *p,
6145                                  struct sec_desc_buf *secdesc_ctr)
6146 {
6147         struct spoolss_security_descriptor *new_secdesc = NULL;
6148         struct spoolss_security_descriptor *old_secdesc = NULL;
6149         const char *printer = NULL;
6150         WERROR result;
6151         int snum = -1;
6152         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6153         struct dcerpc_binding_handle *b;
6154         TALLOC_CTX *tmp_ctx = NULL;
6155         bool ok = false;
6156
6157         if (!Printer) {
6158                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6159                          OUR_HANDLE(handle)));
6160
6161                 result = WERR_INVALID_HANDLE;
6162                 goto done;
6163         }
6164
6165         if (secdesc_ctr == NULL) {
6166                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6167                 result = WERR_INVALID_PARAMETER;
6168                 goto done;
6169         }
6170
6171         switch (Printer->printer_type) {
6172         case SPLHND_SERVER:
6173                 break;
6174         case SPLHND_PRINTER:
6175                 if (!get_printer_snum(p, handle, &snum, NULL)) {
6176                         DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6177                                  OUR_HANDLE(handle)));
6178                         result = WERR_INVALID_HANDLE;
6179                         goto done;
6180                 }
6181                 printer = lp_const_servicename(snum);
6182                 break;
6183         default:
6184                 break;
6185         }
6186
6187         /* Check the user has permissions to change the security
6188            descriptor.  By experimentation with two NT machines, the user
6189            requires Full Access to the printer to change security
6190            information. */
6191
6192         switch (Printer->printer_type) {
6193         case SPLHND_SERVER:
6194                 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6195                 break;
6196         case SPLHND_PRINTER:
6197                 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6198                 break;
6199         default:
6200                 break;
6201         }
6202
6203         if (!ok) {
6204                 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6205                         "(access_granted: 0x%08x)\n", Printer->access_granted));
6206                 result = WERR_ACCESS_DENIED;
6207                 goto done;
6208         }
6209
6210         tmp_ctx = talloc_new(p->mem_ctx);
6211         if (!tmp_ctx) {
6212                 return WERR_NOT_ENOUGH_MEMORY;
6213         }
6214
6215         result = winreg_printer_binding_handle(tmp_ctx,
6216                                                get_session_info_system(),
6217                                                p->msg_ctx,
6218                                                &b);
6219         if (!W_ERROR_IS_OK(result)) {
6220                 goto done;
6221         }
6222
6223         /* NT seems to like setting the security descriptor even though
6224            nothing may have actually changed. */
6225
6226         if (printer != NULL) {
6227                 result = winreg_get_printer_secdesc(tmp_ctx, b,
6228                                                     printer,
6229                                                     &old_secdesc);
6230         } else {
6231                 result = winreg_get_printserver_secdesc(tmp_ctx, b,
6232                                                         &old_secdesc);
6233         }
6234         if (!W_ERROR_IS_OK(result)) {
6235                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6236                 result = WERR_INVALID_HANDLE;
6237                 goto done;
6238         }
6239
6240         if (DEBUGLEVEL >= 10) {
6241                 struct security_acl *the_acl;
6242                 int i;
6243
6244                 the_acl = old_secdesc->dacl;
6245                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6246                            printer, the_acl->num_aces));
6247
6248                 for (i = 0; i < the_acl->num_aces; i++) {
6249                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6250                                            &the_acl->aces[i].trustee),
6251                                   the_acl->aces[i].access_mask));
6252                 }
6253
6254                 the_acl = secdesc_ctr->sd->dacl;
6255
6256                 if (the_acl) {
6257                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6258                                    printer, the_acl->num_aces));
6259
6260                         for (i = 0; i < the_acl->num_aces; i++) {
6261                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6262                                                    &the_acl->aces[i].trustee),
6263                                            the_acl->aces[i].access_mask));
6264                         }
6265                 } else {
6266                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6267                 }
6268         }
6269
6270         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6271         if (new_secdesc == NULL) {
6272                 result = WERR_NOT_ENOUGH_MEMORY;
6273                 goto done;
6274         }
6275
6276         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6277                 result = WERR_OK;
6278                 goto done;
6279         }
6280
6281         if (printer != NULL) {
6282                 result = winreg_set_printer_secdesc(tmp_ctx, b,
6283                                                     printer,
6284                                                     new_secdesc);
6285         } else {
6286                 result = winreg_set_printserver_secdesc(tmp_ctx, b,
6287                                                         new_secdesc);
6288         }
6289
6290 done:
6291         talloc_free(tmp_ctx);
6292         return result;
6293 }
6294
6295 /********************************************************************
6296  Canonicalize printer info from a client
6297  ********************************************************************/
6298
6299 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6300                              struct spoolss_SetPrinterInfo2 *info2,
6301                              int snum)
6302 {
6303         fstring printername;
6304         const char *p;
6305
6306         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6307                 "portname=%s drivername=%s comment=%s location=%s\n",
6308                 info2->servername, info2->printername, info2->sharename,
6309                 info2->portname, info2->drivername, info2->comment,
6310                 info2->location));
6311
6312         /* we force some elements to "correct" values */
6313         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6314         if (info2->servername == NULL) {
6315                 return false;
6316         }
6317         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6318         if (info2->sharename == NULL) {
6319                 return false;
6320         }
6321
6322         /* check to see if we allow printername != sharename */
6323         if (lp_force_printername(snum)) {
6324                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6325                                         lp_netbios_name(), info2->sharename);
6326         } else {
6327                 /* make sure printername is in \\server\printername format */
6328                 fstrcpy(printername, info2->printername);
6329                 p = printername;
6330                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6331                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6332                                 p++;
6333                 }
6334
6335                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6336                                         lp_netbios_name(), p);
6337         }
6338         if (info2->printername == NULL) {
6339                 return false;
6340         }
6341
6342         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6343         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6344
6345         return true;
6346 }
6347
6348 /****************************************************************************
6349 ****************************************************************************/
6350
6351 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6352 {
6353         char *cmd = lp_addport_command(talloc_tos());
6354         char *command = NULL;
6355         int ret;
6356         bool is_print_op = false;
6357
6358         if ( !*cmd ) {
6359                 return WERR_ACCESS_DENIED;
6360         }
6361
6362         command = talloc_asprintf(ctx,
6363                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6364         if (!command) {
6365                 return WERR_NOT_ENOUGH_MEMORY;
6366         }
6367
6368         if ( token )
6369                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6370
6371         DEBUG(10,("Running [%s]\n", command));
6372
6373         /********* BEGIN SePrintOperatorPrivilege **********/
6374
6375         if ( is_print_op )
6376                 become_root();
6377
6378         ret = smbrun(command, NULL, NULL);
6379
6380         if ( is_print_op )
6381                 unbecome_root();
6382
6383         /********* END SePrintOperatorPrivilege **********/
6384
6385         DEBUGADD(10,("returned [%d]\n", ret));
6386
6387         TALLOC_FREE(command);
6388
6389         if ( ret != 0 ) {
6390                 return WERR_ACCESS_DENIED;
6391         }
6392
6393         return WERR_OK;
6394 }
6395
6396 /****************************************************************************
6397 ****************************************************************************/
6398
6399 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6400                                    int snum)
6401 {
6402         /*
6403          * As we do not know if we are embedded in the file server process
6404          * or not, we have to pretend that all shares are in use.
6405          */
6406         return true;
6407 }
6408
6409 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6410                              struct spoolss_SetPrinterInfo2 *info2,
6411                              const char *remote_machine,
6412                              struct messaging_context *msg_ctx)
6413 {
6414         char *cmd = lp_addprinter_command(talloc_tos());
6415         char **qlines;
6416         char *command = NULL;
6417         int numlines;
6418         int ret;
6419         int fd;
6420         bool is_print_op = false;
6421
6422         if (!remote_machine) {
6423                 return false;
6424         }
6425
6426         command = talloc_asprintf(ctx,
6427                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6428                         cmd, info2->printername, info2->sharename,
6429                         info2->portname, info2->drivername,
6430                         info2->location, info2->comment, remote_machine);
6431         if (!command) {
6432                 return false;
6433         }
6434
6435         if ( token )
6436                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6437
6438         DEBUG(10,("Running [%s]\n", command));
6439
6440         /********* BEGIN SePrintOperatorPrivilege **********/
6441
6442         if ( is_print_op )
6443                 become_root();
6444
6445         ret = smbrun(command, &fd, NULL);
6446         if (ret == 0) {
6447                 /* Tell everyone we updated smb.conf. */
6448                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
6449         }
6450
6451         if ( is_print_op )
6452                 unbecome_root();
6453
6454         /********* END SePrintOperatorPrivilege **********/
6455
6456         DEBUGADD(10,("returned [%d]\n", ret));
6457
6458         TALLOC_FREE(command);
6459
6460         if ( ret != 0 ) {
6461                 if (fd != -1)
6462                         close(fd);
6463                 return false;
6464         }
6465
6466         /* reload our services immediately */
6467         become_root();
6468         reload_services(NULL, spoolss_conn_snum_used, false);
6469         unbecome_root();
6470
6471         numlines = 0;
6472         /* Get lines and convert them back to dos-codepage */
6473         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6474         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6475         close(fd);
6476
6477         /* Set the portname to what the script says the portname should be. */
6478         /* but don't require anything to be return from the script exit a good error code */
6479
6480         if (numlines) {
6481                 /* Set the portname to what the script says the portname should be. */
6482                 info2->portname = talloc_strdup(ctx, qlines[0]);
6483                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6484         }
6485
6486         TALLOC_FREE(qlines);
6487         return true;
6488 }
6489
6490 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6491                                const struct auth_session_info *session_info,
6492                                struct messaging_context *msg_ctx,
6493                                int snum,
6494                                struct spoolss_SetPrinterInfo2 *printer,
6495                                struct spoolss_PrinterInfo2 *old_printer)
6496 {
6497         bool force_update = (old_printer == NULL);
6498         const char *dnsdomname;
6499         const char *longname;
6500         const char *uncname;
6501         const char *spooling;
6502         DATA_BLOB buffer;
6503         WERROR result = WERR_OK;
6504         struct dcerpc_binding_handle *b;
6505         TALLOC_CTX *tmp_ctx;
6506         bool ok;
6507
6508         tmp_ctx = talloc_new(mem_ctx);
6509         if (!tmp_ctx) {
6510                 return WERR_NOT_ENOUGH_MEMORY;
6511         }
6512
6513         result = winreg_printer_binding_handle(tmp_ctx,
6514                                                session_info,
6515                                                msg_ctx,
6516                                                &b);
6517         if (!W_ERROR_IS_OK(result)) {
6518                 goto done;
6519         }
6520
6521         if (printer->drivername != NULL &&
6522             (force_update ||
6523              !strequal(printer->drivername, old_printer->drivername))) {
6524                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6525                 if (!ok) {
6526                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6527                         result = WERR_INVALID_DATA;
6528                         goto done;
6529                 }
6530                 result = winreg_set_printer_dataex(tmp_ctx, b,
6531                                           printer->sharename,
6532                                           SPOOL_DSSPOOLER_KEY,
6533                                           SPOOL_REG_DRIVERNAME,
6534                                           REG_SZ,
6535                                           buffer.data,
6536                                           buffer.length);
6537                 if (!W_ERROR_IS_OK(result)) {
6538                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6539                         goto done;
6540                 }
6541
6542                 if (!force_update) {
6543                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6544                                 printer->drivername));
6545
6546                         notify_printer_driver(server_event_context(), msg_ctx,
6547                                               snum, printer->drivername ?
6548                                               printer->drivername : "");
6549                 }
6550         }
6551
6552         if (printer->comment != NULL &&
6553             (force_update ||
6554              !strequal(printer->comment, old_printer->comment))) {
6555                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6556                 if (!ok) {
6557                         DEBUG(0, ("comment data corrupted\n"));
6558                         result = WERR_INVALID_DATA;
6559                         goto done;
6560                 }
6561                 result = winreg_set_printer_dataex(tmp_ctx, b,
6562                                           printer->sharename,
6563                                           SPOOL_DSSPOOLER_KEY,
6564                                           SPOOL_REG_DESCRIPTION,
6565                                           REG_SZ,
6566                                           buffer.data,
6567                                           buffer.length);
6568                 if (!W_ERROR_IS_OK(result)) {
6569                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6570                         goto done;
6571                 }
6572
6573                 if (!force_update) {
6574                         notify_printer_comment(server_event_context(), msg_ctx,
6575                                                snum, printer->comment ?
6576                                                printer->comment : "");
6577                 }
6578         }
6579
6580         if (printer->sharename != NULL &&
6581             (force_update ||
6582              !strequal(printer->sharename, old_printer->sharename))) {
6583                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6584                 if (!ok) {
6585                         DEBUG(0, ("sharename data corrupted\n"));
6586                         result = WERR_INVALID_DATA;
6587                         goto done;
6588                 }
6589                 result = winreg_set_printer_dataex(tmp_ctx, b,
6590                                           printer->sharename,
6591                                           SPOOL_DSSPOOLER_KEY,
6592                                           SPOOL_REG_PRINTSHARENAME,
6593                                           REG_SZ,
6594                                           buffer.data,
6595                                           buffer.length);
6596                 if (!W_ERROR_IS_OK(result)) {
6597                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6598                         goto done;
6599                 }
6600
6601                 if (!force_update) {
6602                         notify_printer_sharename(server_event_context(),
6603                                                  msg_ctx,
6604                                                  snum, printer->sharename ?
6605                                                  printer->sharename : "");
6606                 }
6607
6608                 /* name change, purge any cache entries for the old */
6609                 prune_printername_cache();
6610         }
6611
6612         if (printer->printername != NULL &&
6613             (force_update ||
6614              !strequal(printer->printername, old_printer->printername))) {
6615                 const char *p;
6616
6617                 p = strrchr(printer->printername, '\\' );
6618                 if (p != NULL) {
6619                         p++;
6620                 } else {
6621                         p = printer->printername;
6622                 }
6623
6624                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6625                 if (!ok) {
6626                         DEBUG(0, ("printername data corrupted\n"));
6627                         result = WERR_INVALID_DATA;
6628                         goto done;
6629                 }
6630                 result = winreg_set_printer_dataex(tmp_ctx, b,
6631                                           printer->sharename,
6632                                           SPOOL_DSSPOOLER_KEY,
6633                                           SPOOL_REG_PRINTERNAME,
6634                                           REG_SZ,
6635                                           buffer.data,
6636                                           buffer.length);
6637                 if (!W_ERROR_IS_OK(result)) {
6638                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6639                         goto done;
6640                 }
6641
6642                 if (!force_update) {
6643                         notify_printer_printername(server_event_context(),
6644                                                    msg_ctx, snum, p ? p : "");
6645                 }
6646
6647                 /* name change, purge any cache entries for the old */
6648                 prune_printername_cache();
6649         }
6650
6651         if (printer->portname != NULL &&
6652             (force_update ||
6653              !strequal(printer->portname, old_printer->portname))) {
6654                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6655                 if (!ok) {
6656                         DEBUG(0, ("portname data corrupted\n"));
6657                         result = WERR_INVALID_DATA;
6658                         goto done;
6659                 }
6660                 result = winreg_set_printer_dataex(tmp_ctx, b,
6661                                           printer->sharename,
6662                                           SPOOL_DSSPOOLER_KEY,
6663                                           SPOOL_REG_PORTNAME,
6664                                           REG_SZ,
6665                                           buffer.data,
6666                                           buffer.length);
6667                 if (!W_ERROR_IS_OK(result)) {
6668                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6669                         goto done;
6670                 }
6671
6672                 if (!force_update) {
6673                         notify_printer_port(server_event_context(),
6674                                             msg_ctx, snum, printer->portname ?
6675                                             printer->portname : "");
6676                 }
6677         }
6678
6679         if (printer->location != NULL &&
6680             (force_update ||
6681              !strequal(printer->location, old_printer->location))) {
6682                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6683                 if (!ok) {
6684                         DEBUG(0, ("location data corrupted\n"));
6685                         result = WERR_INVALID_DATA;
6686                         goto done;
6687                 }
6688                 result = winreg_set_printer_dataex(tmp_ctx, b,
6689                                           printer->sharename,
6690                                           SPOOL_DSSPOOLER_KEY,
6691                                           SPOOL_REG_LOCATION,
6692                                           REG_SZ,
6693                                           buffer.data,
6694                                           buffer.length);
6695                 if (!W_ERROR_IS_OK(result)) {
6696                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6697                         goto done;
6698                 }
6699
6700                 if (!force_update) {
6701                         notify_printer_location(server_event_context(),
6702                                                 msg_ctx, snum,
6703                                                 printer->location ?
6704                                                 printer->location : "");
6705                 }
6706         }
6707
6708         if (printer->sepfile != NULL &&
6709             (force_update ||
6710              !strequal(printer->sepfile, old_printer->sepfile))) {
6711                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6712                 if (!ok) {
6713                         DEBUG(0, ("sepfile data corrupted\n"));
6714                         result = WERR_INVALID_DATA;
6715                         goto done;
6716                 }
6717                 result = winreg_set_printer_dataex(tmp_ctx, b,
6718                                           printer->sharename,
6719                                           SPOOL_DSSPOOLER_KEY,
6720                                           SPOOL_REG_PRINTSEPARATORFILE,
6721                                           REG_SZ,
6722                                           buffer.data,
6723                                           buffer.length);
6724                 if (!W_ERROR_IS_OK(result)) {
6725                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6726                         goto done;
6727                 }
6728
6729                 if (!force_update) {
6730                         notify_printer_sepfile(server_event_context(),
6731                                                msg_ctx, snum,
6732                                                printer->sepfile ?
6733                                                printer->sepfile : "");
6734                 }
6735         }
6736
6737         if (printer->starttime != 0 &&
6738             (force_update ||
6739              printer->starttime != old_printer->starttime)) {
6740                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6741                 SIVAL(buffer.data, 0, printer->starttime);
6742                 result = winreg_set_printer_dataex(tmp_ctx, b,
6743                                           printer->sharename,
6744                                           SPOOL_DSSPOOLER_KEY,
6745                                           SPOOL_REG_PRINTSTARTTIME,
6746                                           REG_DWORD,
6747                                           buffer.data,
6748                                           buffer.length);
6749                 if (!W_ERROR_IS_OK(result)) {
6750                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6751                         goto done;
6752                 }
6753         }
6754
6755         if (printer->untiltime != 0 &&
6756             (force_update ||
6757              printer->untiltime != old_printer->untiltime)) {
6758                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6759                 SIVAL(buffer.data, 0, printer->untiltime);
6760                 result = winreg_set_printer_dataex(tmp_ctx, b,
6761                                           printer->sharename,
6762                                           SPOOL_DSSPOOLER_KEY,
6763                                           SPOOL_REG_PRINTENDTIME,
6764                                           REG_DWORD,
6765                                           buffer.data,
6766                                           buffer.length);
6767                 if (!W_ERROR_IS_OK(result)) {
6768                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6769                         goto done;
6770                 }
6771         }
6772
6773         if (force_update || printer->priority != old_printer->priority) {
6774                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6775                 SIVAL(buffer.data, 0, printer->priority);
6776                 result = winreg_set_printer_dataex(tmp_ctx, b,
6777                                           printer->sharename,
6778                                           SPOOL_DSSPOOLER_KEY,
6779                                           SPOOL_REG_PRIORITY,
6780                                           REG_DWORD,
6781                                           buffer.data,
6782                                           buffer.length);
6783                 if (!W_ERROR_IS_OK(result)) {
6784                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6785                         goto done;
6786                 }
6787         }
6788
6789         if (force_update || printer->attributes != old_printer->attributes) {
6790                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6791                 SIVAL(buffer.data, 0, (printer->attributes &
6792                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6793                 result = winreg_set_printer_dataex(tmp_ctx, b,
6794                                           printer->sharename,
6795                                           SPOOL_DSSPOOLER_KEY,
6796                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6797                                           REG_DWORD,
6798                                           buffer.data,
6799                                           buffer.length);
6800                 if (!W_ERROR_IS_OK(result)) {
6801                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6802                         goto done;
6803                 }
6804
6805                 switch (printer->attributes & 0x3) {
6806                         case 0:
6807                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6808                                 break;
6809                         case 1:
6810                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6811                                 break;
6812                         case 2:
6813                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6814                                 break;
6815                         default:
6816                                 spooling = "unknown";
6817                 }
6818                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6819                 if (!ok) {
6820                         DEBUG(0, ("printSpooling data corrupted\n"));
6821                         result = WERR_INVALID_DATA;
6822                         goto done;
6823                 }
6824                 winreg_set_printer_dataex(tmp_ctx, b,
6825                                           printer->sharename,
6826                                           SPOOL_DSSPOOLER_KEY,
6827                                           SPOOL_REG_PRINTSPOOLING,
6828                                           REG_SZ,
6829                                           buffer.data,
6830                                           buffer.length);
6831         }
6832
6833         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6834         if (!ok) {
6835                 DEBUG(0, ("shortServerName data corrupted\n"));
6836                 result = WERR_INVALID_DATA;
6837                 goto done;
6838         }
6839         result = winreg_set_printer_dataex(tmp_ctx, b,
6840                                   printer->sharename,
6841                                   SPOOL_DSSPOOLER_KEY,
6842                                   SPOOL_REG_SHORTSERVERNAME,
6843                                   REG_SZ,
6844                                   buffer.data,
6845                                   buffer.length);
6846         if (!W_ERROR_IS_OK(result)) {
6847                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6848                 goto done;
6849         }
6850
6851         dnsdomname = get_mydnsfullname();
6852         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6853                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6854         } else {
6855                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6856         }
6857         if (longname == NULL) {
6858                 result = WERR_NOT_ENOUGH_MEMORY;
6859                 goto done;
6860         }
6861
6862         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6863         if (!ok) {
6864                 DEBUG(0, ("longname data corrupted\n"));
6865                 result = WERR_INVALID_DATA;
6866                 goto done;
6867         }
6868         result = winreg_set_printer_dataex(tmp_ctx, b,
6869                                            printer->sharename,
6870                                            SPOOL_DSSPOOLER_KEY,
6871                                            SPOOL_REG_SERVERNAME,
6872                                            REG_SZ,
6873                                            buffer.data,
6874                                            buffer.length);
6875         if (!W_ERROR_IS_OK(result)) {
6876                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6877                 goto done;
6878         }
6879
6880         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6881                                   lp_netbios_name(), printer->sharename);
6882         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6883         if (!ok) {
6884                 DEBUG(0, ("uncName data corrupted\n"));
6885                 result = WERR_INVALID_DATA;
6886                 goto done;
6887         }
6888         result = winreg_set_printer_dataex(tmp_ctx, b,
6889                                   printer->sharename,
6890                                   SPOOL_DSSPOOLER_KEY,
6891                                   SPOOL_REG_UNCNAME,
6892                                   REG_SZ,
6893                                   buffer.data,
6894                                   buffer.length);
6895         if (!W_ERROR_IS_OK(result)) {
6896                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6897                 goto done;
6898         }
6899
6900 done:
6901         talloc_free(tmp_ctx);
6902         return result;
6903 }
6904
6905 /********************************************************************
6906  * Called by spoolss_api_setprinter
6907  * when updating a printer description.
6908  ********************************************************************/
6909
6910 static WERROR update_printer(struct pipes_struct *p,
6911                              struct policy_handle *handle,
6912                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6913                              struct spoolss_DeviceMode *devmode)
6914 {
6915         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6916         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6917         struct spoolss_PrinterInfo2 *old_printer;
6918         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6919         int snum;
6920         WERROR result = WERR_OK;
6921         TALLOC_CTX *tmp_ctx;
6922         struct dcerpc_binding_handle *b;
6923
6924         DEBUG(8,("update_printer\n"));
6925
6926         tmp_ctx = talloc_new(p->mem_ctx);
6927         if (tmp_ctx == NULL) {
6928                 return WERR_NOT_ENOUGH_MEMORY;
6929         }
6930
6931         if (!Printer) {
6932                 result = WERR_INVALID_HANDLE;
6933                 goto done;
6934         }
6935
6936         if (!get_printer_snum(p, handle, &snum, NULL)) {
6937                 result = WERR_INVALID_HANDLE;
6938                 goto done;
6939         }
6940
6941         result = winreg_printer_binding_handle(tmp_ctx,
6942                                                get_session_info_system(),
6943                                                p->msg_ctx,
6944                                                &b);
6945         if (!W_ERROR_IS_OK(result)) {
6946                 goto done;
6947         }
6948
6949         result = winreg_get_printer(tmp_ctx, b,
6950                                     lp_const_servicename(snum),
6951                                     &old_printer);
6952         if (!W_ERROR_IS_OK(result)) {
6953                 result = WERR_INVALID_HANDLE;
6954                 goto done;
6955         }
6956
6957         /* Do sanity check on the requested changes for Samba */
6958         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6959                 result = WERR_INVALID_PARAMETER;
6960                 goto done;
6961         }
6962
6963         /* FIXME!!! If the driver has changed we really should verify that
6964            it is installed before doing much else   --jerry */
6965
6966         /* Check calling user has permission to update printer description */
6967         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6968                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6969                 result = WERR_ACCESS_DENIED;
6970                 goto done;
6971         }
6972
6973         /* Call addprinter hook */
6974         /* Check changes to see if this is really needed */
6975
6976         if (*lp_addprinter_command(talloc_tos()) &&
6977                         (!strequal(printer->drivername, old_printer->drivername) ||
6978                          !strequal(printer->comment, old_printer->comment) ||
6979                          !strequal(printer->portname, old_printer->portname) ||
6980                          !strequal(printer->location, old_printer->location)) )
6981         {
6982                 char *raddr;
6983
6984                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6985                                                          p->mem_ctx);
6986                 if (raddr == NULL) {
6987                         return WERR_NOT_ENOUGH_MEMORY;
6988                 }
6989
6990                 /* add_printer_hook() will call reload_services() */
6991                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6992                                       printer, raddr,
6993                                       p->msg_ctx)) {
6994                         result = WERR_ACCESS_DENIED;
6995                         goto done;
6996                 }
6997         }
6998
6999         result = update_dsspooler(tmp_ctx,
7000                                   get_session_info_system(),
7001                                   p->msg_ctx,
7002                                   snum,
7003                                   printer,
7004                                   old_printer);
7005         if (!W_ERROR_IS_OK(result)) {
7006                 goto done;
7007         }
7008
7009         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
7010
7011         if (devmode == NULL) {
7012                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
7013         }
7014         result = winreg_update_printer(tmp_ctx, b,
7015                                        printer->sharename,
7016                                        printer_mask,
7017                                        printer,
7018                                        devmode,
7019                                        NULL);
7020
7021 done:
7022         talloc_free(tmp_ctx);
7023
7024         return result;
7025 }
7026
7027 /****************************************************************************
7028 ****************************************************************************/
7029 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
7030                                            struct policy_handle *handle,
7031                                            struct spoolss_SetPrinterInfo7 *info7)
7032 {
7033 #ifdef HAVE_ADS
7034         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7035         WERROR result;
7036         int snum;
7037         struct printer_handle *Printer;
7038
7039         if ( lp_security() != SEC_ADS ) {
7040                 return WERR_INVALID_LEVEL;
7041         }
7042
7043         Printer = find_printer_index_by_hnd(p, handle);
7044
7045         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
7046
7047         if (!Printer)
7048                 return WERR_INVALID_HANDLE;
7049
7050         if (!get_printer_snum(p, handle, &snum, NULL))
7051                 return WERR_INVALID_HANDLE;
7052
7053         result = winreg_get_printer_internal(p->mem_ctx,
7054                                     get_session_info_system(),
7055                                     p->msg_ctx,
7056                                     lp_servicename(talloc_tos(), snum),
7057                                     &pinfo2);
7058         if (!W_ERROR_IS_OK(result)) {
7059                 return WERR_INVALID_HANDLE;
7060         }
7061
7062         nt_printer_publish(pinfo2,
7063                            get_session_info_system(),
7064                            p->msg_ctx,
7065                            pinfo2,
7066                            info7->action);
7067
7068         TALLOC_FREE(pinfo2);
7069         return WERR_OK;
7070 #else
7071         return WERR_INVALID_LEVEL;
7072 #endif
7073 }
7074
7075 /********************************************************************
7076  ********************************************************************/
7077
7078 static WERROR update_printer_devmode(struct pipes_struct *p,
7079                                      struct policy_handle *handle,
7080                                      struct spoolss_DeviceMode *devmode)
7081 {
7082         int snum;
7083         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7084         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7085
7086         DEBUG(8,("update_printer_devmode\n"));
7087
7088         if (!Printer) {
7089                 return WERR_INVALID_HANDLE;
7090         }
7091
7092         if (!get_printer_snum(p, handle, &snum, NULL)) {
7093                 return WERR_INVALID_HANDLE;
7094         }
7095
7096         /* Check calling user has permission to update printer description */
7097         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7098                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7099                 return WERR_ACCESS_DENIED;
7100         }
7101
7102         return winreg_update_printer_internal(p->mem_ctx,
7103                                      get_session_info_system(),
7104                                      p->msg_ctx,
7105                                      lp_const_servicename(snum),
7106                                      info2_mask,
7107                                      NULL,
7108                                      devmode,
7109                                      NULL);
7110 }
7111
7112
7113 /****************************************************************
7114  _spoolss_SetPrinter
7115 ****************************************************************/
7116
7117 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7118                            struct spoolss_SetPrinter *r)
7119 {
7120         WERROR result;
7121
7122         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7123
7124         if (!Printer) {
7125                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7126                         OUR_HANDLE(r->in.handle)));
7127                 return WERR_INVALID_HANDLE;
7128         }
7129
7130         /* check the level */
7131         switch (r->in.info_ctr->level) {
7132                 case 0:
7133                         return control_printer(r->in.handle, r->in.command, p);
7134                 case 2:
7135                         result = update_printer(p, r->in.handle,
7136                                                 r->in.info_ctr,
7137                                                 r->in.devmode_ctr->devmode);
7138                         if (!W_ERROR_IS_OK(result))
7139                                 return result;
7140                         if (r->in.secdesc_ctr->sd)
7141                                 result = update_printer_sec(r->in.handle, p,
7142                                                             r->in.secdesc_ctr);
7143                         return result;
7144                 case 3:
7145                         return update_printer_sec(r->in.handle, p,
7146                                                   r->in.secdesc_ctr);
7147                 case 4: {
7148                         struct spoolss_PrinterInfo2 *old_printer;
7149                         struct spoolss_SetPrinterInfo2 *set_old_printer;
7150                         struct spoolss_SetPrinterInfoCtr *info_ctr;
7151                         struct dcerpc_binding_handle *b;
7152                         int snum;
7153                         TALLOC_CTX *tmp_ctx;
7154
7155                         tmp_ctx = talloc_new(p->mem_ctx);
7156                         if (tmp_ctx == NULL) {
7157                                 return WERR_NOT_ENOUGH_MEMORY;
7158                         }
7159
7160                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7161                                 TALLOC_FREE(tmp_ctx);
7162                                 return WERR_INVALID_HANDLE;
7163                         }
7164
7165                         result = winreg_printer_binding_handle(tmp_ctx,
7166                                                                get_session_info_system(),
7167                                                                p->msg_ctx,
7168                                                                &b);
7169                         if (!W_ERROR_IS_OK(result)) {
7170                                 TALLOC_FREE(tmp_ctx);
7171                                 return result;
7172                         }
7173
7174                         result = winreg_get_printer(tmp_ctx, b,
7175                                                     lp_const_servicename(snum),
7176                                                     &old_printer);
7177                         if (!W_ERROR_IS_OK(result)) {
7178                                 TALLOC_FREE(tmp_ctx);
7179                                 return WERR_INVALID_HANDLE;
7180                         }
7181
7182                         old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7183                         if (old_printer->servername == NULL) {
7184                                 TALLOC_FREE(tmp_ctx);
7185                                 return WERR_NOT_ENOUGH_MEMORY;
7186                         }
7187
7188                         old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7189                         if (old_printer->printername == NULL) {
7190                                 TALLOC_FREE(tmp_ctx);
7191                                 return WERR_NOT_ENOUGH_MEMORY;
7192                         }
7193
7194                         old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7195
7196                         set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7197                         if (set_old_printer == NULL) {
7198                                 TALLOC_FREE(tmp_ctx);
7199                                 return WERR_NOT_ENOUGH_MEMORY;
7200                         }
7201
7202                         spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7203
7204                         info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7205                         if (info_ctr == NULL) {
7206                                 TALLOC_FREE(tmp_ctx);
7207                                 return WERR_NOT_ENOUGH_MEMORY;
7208                         }
7209
7210                         info_ctr->level = 2;
7211                         info_ctr->info.info2 = set_old_printer;
7212
7213                         result = update_printer(p, r->in.handle,
7214                                                 info_ctr,
7215                                                 r->in.devmode_ctr->devmode);
7216
7217                         if (!W_ERROR_IS_OK(result)) {
7218                                 TALLOC_FREE(tmp_ctx);
7219                                 return result;
7220                         }
7221
7222                         if (r->in.secdesc_ctr->sd) {
7223                                 result = update_printer_sec(r->in.handle, p,
7224                                                             r->in.secdesc_ctr);
7225                         }
7226
7227                         TALLOC_FREE(tmp_ctx);
7228                         return result;
7229                 }
7230                 case 7:
7231                         return publish_or_unpublish_printer(p, r->in.handle,
7232                                                             r->in.info_ctr->info.info7);
7233                 case 8:
7234                         return update_printer_devmode(p, r->in.handle,
7235                                                       r->in.devmode_ctr->devmode);
7236                 default:
7237                         return WERR_INVALID_LEVEL;
7238         }
7239 }
7240
7241 /****************************************************************
7242  _spoolss_FindClosePrinterNotify
7243 ****************************************************************/
7244
7245 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7246                                        struct spoolss_FindClosePrinterNotify *r)
7247 {
7248         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7249
7250         if (!Printer) {
7251                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7252                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7253                 return WERR_INVALID_HANDLE;
7254         }
7255
7256         if (Printer->notify.cli_chan != NULL &&
7257             Printer->notify.cli_chan->active_connections > 0) {
7258                 int snum = -1;
7259
7260                 if (Printer->printer_type == SPLHND_PRINTER) {
7261                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7262                                 return WERR_INVALID_HANDLE;
7263                         }
7264                 }
7265
7266                 srv_spoolss_replycloseprinter(snum, Printer);
7267         }
7268
7269         Printer->notify.flags=0;
7270         Printer->notify.options=0;
7271         Printer->notify.localmachine[0]='\0';
7272         Printer->notify.printerlocal=0;
7273         TALLOC_FREE(Printer->notify.option);
7274
7275         return WERR_OK;
7276 }
7277
7278 /****************************************************************
7279  _spoolss_AddJob
7280 ****************************************************************/
7281
7282 WERROR _spoolss_AddJob(struct pipes_struct *p,
7283                        struct spoolss_AddJob *r)
7284 {
7285         if (!r->in.buffer && (r->in.offered != 0)) {
7286                 return WERR_INVALID_PARAMETER;
7287         }
7288
7289         /* this is what a NT server returns for AddJob. AddJob must fail on
7290          * non-local printers */
7291
7292         if (r->in.level != 1) {
7293                 return WERR_INVALID_LEVEL;
7294         }
7295
7296         return WERR_INVALID_PARAMETER;
7297 }
7298
7299 /****************************************************************************
7300 fill_job_info1
7301 ****************************************************************************/
7302
7303 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7304                              struct spoolss_JobInfo1 *r,
7305                              const print_queue_struct *queue,
7306                              uint32_t jobid,
7307                              int position, int snum,
7308                              struct spoolss_PrinterInfo2 *pinfo2)
7309 {
7310         struct tm *t;
7311
7312         t = gmtime(&queue->time);
7313
7314         r->job_id               = jobid;
7315
7316         r->printer_name         = lp_servicename(mem_ctx, snum);
7317         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7318         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7319         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7320         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7321         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7322         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7323         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7324         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7325         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7326         r->text_status          = talloc_strdup(mem_ctx, "");
7327         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7328
7329         r->status               = nt_printj_status(queue->status);
7330         r->priority             = queue->priority;
7331         r->position             = position;
7332         r->total_pages          = queue->page_count;
7333         r->pages_printed        = 0; /* ??? */
7334
7335         init_systemtime(&r->submitted, t);
7336
7337         return WERR_OK;
7338 }
7339
7340 /****************************************************************************
7341 fill_job_info2
7342 ****************************************************************************/
7343
7344 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7345                              struct spoolss_JobInfo2 *r,
7346                              const print_queue_struct *queue,
7347                              uint32_t jobid,
7348                              int position, int snum,
7349                              struct spoolss_PrinterInfo2 *pinfo2,
7350                              struct spoolss_DeviceMode *devmode)
7351 {
7352         struct tm *t;
7353
7354         t = gmtime(&queue->time);
7355
7356         r->job_id               = jobid;
7357
7358         r->printer_name         = lp_servicename(mem_ctx, snum);
7359         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7360         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7361         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7362         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7363         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7364         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7365         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7366         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7367         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7368         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7369         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7370         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7371         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7372         r->parameters           = talloc_strdup(mem_ctx, "");
7373         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7374         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7375         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7376
7377         r->devmode              = devmode;
7378
7379         r->text_status          = talloc_strdup(mem_ctx, "");
7380         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7381
7382         r->secdesc              = NULL;
7383
7384         r->status               = nt_printj_status(queue->status);
7385         r->priority             = queue->priority;
7386         r->position             = position;
7387         r->start_time           = 0;
7388         r->until_time           = 0;
7389         r->total_pages          = queue->page_count;
7390         r->size                 = queue->size;
7391         init_systemtime(&r->submitted, t);
7392         r->time                 = 0;
7393         r->pages_printed        = 0; /* ??? */
7394
7395         return WERR_OK;
7396 }
7397
7398 /****************************************************************************
7399  Enumjobs at level 1.
7400 ****************************************************************************/
7401
7402 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7403                               const print_queue_struct *queue,
7404                               uint32_t num_queues, int snum,
7405                               struct spoolss_PrinterInfo2 *pinfo2,
7406                               union spoolss_JobInfo **info_p,
7407                               uint32_t *count)
7408 {
7409         union spoolss_JobInfo *info;
7410         int i;
7411         WERROR result = WERR_OK;
7412         uint32_t num_filled;
7413         struct tdb_print_db *pdb;
7414
7415         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7416         if (info == NULL) {
7417                 result = WERR_NOT_ENOUGH_MEMORY;
7418                 goto err_out;
7419         }
7420
7421         pdb = get_print_db_byname(pinfo2->sharename);
7422         if (pdb == NULL) {
7423                 result = WERR_INVALID_PARAMETER;
7424                 goto err_info_free;
7425         }
7426
7427         num_filled = 0;
7428         for (i = 0; i < num_queues; i++) {
7429                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7430                 if (jobid == (uint32_t)-1) {
7431                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7432                         continue;
7433                 }
7434
7435                 result = fill_job_info1(info,
7436                                         &info[num_filled].info1,
7437                                         &queue[i],
7438                                         jobid,
7439                                         i,
7440                                         snum,
7441                                         pinfo2);
7442                 if (!W_ERROR_IS_OK(result)) {
7443                         goto err_pdb_drop;
7444                 }
7445
7446                 num_filled++;
7447         }
7448
7449         release_print_db(pdb);
7450         *info_p = info;
7451         *count = num_filled;
7452
7453         return WERR_OK;
7454
7455 err_pdb_drop:
7456         release_print_db(pdb);
7457 err_info_free:
7458         TALLOC_FREE(info);
7459 err_out:
7460         *count = 0;
7461         return result;
7462 }
7463
7464 /****************************************************************************
7465  Enumjobs at level 2.
7466 ****************************************************************************/
7467
7468 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7469                               const print_queue_struct *queue,
7470                               uint32_t num_queues, int snum,
7471                               struct spoolss_PrinterInfo2 *pinfo2,
7472                               union spoolss_JobInfo **info_p,
7473                               uint32_t *count)
7474 {
7475         union spoolss_JobInfo *info;
7476         int i;
7477         WERROR result = WERR_OK;
7478         uint32_t num_filled;
7479         struct tdb_print_db *pdb;
7480
7481         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7482         if (info == NULL) {
7483                 result = WERR_NOT_ENOUGH_MEMORY;
7484                 goto err_out;
7485         }
7486
7487         pdb = get_print_db_byname(pinfo2->sharename);
7488         if (pdb == NULL) {
7489                 result = WERR_INVALID_PARAMETER;
7490                 goto err_info_free;
7491         }
7492
7493         num_filled = 0;
7494         for (i = 0; i< num_queues; i++) {
7495                 struct spoolss_DeviceMode *devmode;
7496                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7497                 if (jobid == (uint32_t)-1) {
7498                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7499                         continue;
7500                 }
7501
7502                 result = spoolss_create_default_devmode(info,
7503                                                         pinfo2->printername,
7504                                                         &devmode);
7505                 if (!W_ERROR_IS_OK(result)) {
7506                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7507                         goto err_pdb_drop;
7508                 }
7509
7510                 result = fill_job_info2(info,
7511                                         &info[num_filled].info2,
7512                                         &queue[i],
7513                                         jobid,
7514                                         i,
7515                                         snum,
7516                                         pinfo2,
7517                                         devmode);
7518                 if (!W_ERROR_IS_OK(result)) {
7519                         goto err_pdb_drop;
7520                 }
7521                 num_filled++;
7522         }
7523
7524         release_print_db(pdb);
7525         *info_p = info;
7526         *count = num_filled;
7527
7528         return WERR_OK;
7529
7530 err_pdb_drop:
7531         release_print_db(pdb);
7532 err_info_free:
7533         TALLOC_FREE(info);
7534 err_out:
7535         *count = 0;
7536         return result;
7537 }
7538
7539 /****************************************************************************
7540  Enumjobs at level 3.
7541 ****************************************************************************/
7542
7543 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7544                               const print_queue_struct *queue,
7545                               uint32_t num_queues, int snum,
7546                               struct spoolss_PrinterInfo2 *pinfo2,
7547                               union spoolss_JobInfo **info_p,
7548                               uint32_t *count)
7549 {
7550         union spoolss_JobInfo *info;
7551         int i;
7552         WERROR result = WERR_OK;
7553         uint32_t num_filled;
7554         struct tdb_print_db *pdb;
7555
7556         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7557         if (info == NULL) {
7558                 result = WERR_NOT_ENOUGH_MEMORY;
7559                 goto err_out;
7560         }
7561
7562         pdb = get_print_db_byname(pinfo2->sharename);
7563         if (pdb == NULL) {
7564                 result = WERR_INVALID_PARAMETER;
7565                 goto err_info_free;
7566         }
7567
7568         num_filled = 0;
7569         for (i = 0; i < num_queues; i++) {
7570                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7571                 if (jobid == (uint32_t)-1) {
7572                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7573                         continue;
7574                 }
7575
7576                 info[num_filled].info3.job_id = jobid;
7577                 /* next_job_id is overwritten on next iteration */
7578                 info[num_filled].info3.next_job_id = 0;
7579                 info[num_filled].info3.reserved = 0;
7580
7581                 if (num_filled > 0) {
7582                         info[num_filled - 1].info3.next_job_id = jobid;
7583                 }
7584                 num_filled++;
7585         }
7586
7587         release_print_db(pdb);
7588         *info_p = info;
7589         *count = num_filled;
7590
7591         return WERR_OK;
7592
7593 err_info_free:
7594         TALLOC_FREE(info);
7595 err_out:
7596         *count = 0;
7597         return result;
7598 }
7599
7600 /****************************************************************
7601  _spoolss_EnumJobs
7602 ****************************************************************/
7603
7604 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7605                          struct spoolss_EnumJobs *r)
7606 {
7607         WERROR result;
7608         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7609         int snum;
7610         print_status_struct prt_status;
7611         print_queue_struct *queue = NULL;
7612         uint32_t count;
7613
7614         /* that's an [in out] buffer */
7615
7616         if (!r->in.buffer && (r->in.offered != 0)) {
7617                 return WERR_INVALID_PARAMETER;
7618         }
7619
7620         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7621                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7622                 return WERR_INVALID_LEVEL;
7623         }
7624
7625         DEBUG(4,("_spoolss_EnumJobs\n"));
7626
7627         *r->out.needed = 0;
7628         *r->out.count = 0;
7629         *r->out.info = NULL;
7630
7631         /* lookup the printer snum and tdb entry */
7632
7633         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7634                 return WERR_INVALID_HANDLE;
7635         }
7636
7637         result = winreg_get_printer_internal(p->mem_ctx,
7638                                     get_session_info_system(),
7639                                     p->msg_ctx,
7640                                     lp_const_servicename(snum),
7641                                     &pinfo2);
7642         if (!W_ERROR_IS_OK(result)) {
7643                 return result;
7644         }
7645
7646         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7647         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7648                 count, prt_status.status, prt_status.message));
7649
7650         if (count == 0) {
7651                 SAFE_FREE(queue);
7652                 TALLOC_FREE(pinfo2);
7653                 return WERR_OK;
7654         }
7655
7656         switch (r->in.level) {
7657         case 1:
7658                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7659                                          pinfo2, r->out.info, r->out.count);
7660                 break;
7661         case 2:
7662                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7663                                          pinfo2, r->out.info, r->out.count);
7664                 break;
7665         case 3:
7666                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7667                                          pinfo2, r->out.info, r->out.count);
7668                 break;
7669         default:
7670                 SMB_ASSERT(false);      /* level checked on entry */
7671                 break;
7672         }
7673
7674         SAFE_FREE(queue);
7675         TALLOC_FREE(pinfo2);
7676
7677         if (!W_ERROR_IS_OK(result)) {
7678                 return result;
7679         }
7680
7681         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7682                                                      spoolss_EnumJobs,
7683                                                      *r->out.info, r->in.level,
7684                                                      *r->out.count);
7685         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7686         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7687
7688         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7689 }
7690
7691 /****************************************************************
7692  _spoolss_ScheduleJob
7693 ****************************************************************/
7694
7695 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7696                             struct spoolss_ScheduleJob *r)
7697 {
7698         return WERR_OK;
7699 }
7700
7701 /****************************************************************
7702 ****************************************************************/
7703
7704 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7705                                struct messaging_context *msg_ctx,
7706                                const char *printer_name,
7707                                uint32_t job_id,
7708                                struct spoolss_SetJobInfo1 *r)
7709 {
7710         char *old_doc_name;
7711
7712         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7713                 return WERR_INVALID_HANDLE;
7714         }
7715
7716         if (strequal(old_doc_name, r->document_name)) {
7717                 return WERR_OK;
7718         }
7719
7720         if (!print_job_set_name(server_event_context(), msg_ctx,
7721                                 printer_name, job_id, r->document_name)) {
7722                 return WERR_INVALID_HANDLE;
7723         }
7724
7725         return WERR_OK;
7726 }
7727
7728 /****************************************************************
7729  _spoolss_SetJob
7730 ****************************************************************/
7731
7732 WERROR _spoolss_SetJob(struct pipes_struct *p,
7733                        struct spoolss_SetJob *r)
7734 {
7735         const struct auth_session_info *session_info = p->session_info;
7736         int snum;
7737         WERROR errcode = WERR_INVALID_FUNCTION;
7738
7739         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7740                 return WERR_INVALID_HANDLE;
7741         }
7742
7743         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7744                 return WERR_INVALID_PRINTER_NAME;
7745         }
7746
7747         switch (r->in.command) {
7748         case SPOOLSS_JOB_CONTROL_CANCEL:
7749         case SPOOLSS_JOB_CONTROL_DELETE:
7750                 errcode = print_job_delete(session_info, p->msg_ctx,
7751                                            snum, r->in.job_id);
7752                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7753                         errcode = WERR_OK;
7754                 }
7755                 break;
7756         case SPOOLSS_JOB_CONTROL_PAUSE:
7757                 errcode = print_job_pause(session_info, p->msg_ctx,
7758                                           snum, r->in.job_id);
7759                 break;
7760         case SPOOLSS_JOB_CONTROL_RESTART:
7761         case SPOOLSS_JOB_CONTROL_RESUME:
7762                 errcode = print_job_resume(session_info, p->msg_ctx,
7763                                            snum, r->in.job_id);
7764                 break;
7765         case SPOOLSS_JOB_CONTROL_NOOP:
7766                 errcode = WERR_OK;
7767                 break;
7768         default:
7769                 return WERR_INVALID_LEVEL;
7770         }
7771
7772         if (!W_ERROR_IS_OK(errcode)) {
7773                 return errcode;
7774         }
7775
7776         if (r->in.ctr == NULL) {
7777                 return errcode;
7778         }
7779
7780         switch (r->in.ctr->level) {
7781         case 1:
7782                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7783                                            lp_const_servicename(snum),
7784                                            r->in.job_id,
7785                                            r->in.ctr->info.info1);
7786                 break;
7787         case 2:
7788         case 3:
7789         case 4:
7790         default:
7791                 return WERR_INVALID_LEVEL;
7792         }
7793
7794         return errcode;
7795 }
7796
7797 /****************************************************************************
7798  Enumerates all printer drivers by level and architecture.
7799 ****************************************************************************/
7800
7801 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7802                                                        const struct auth_session_info *session_info,
7803                                                        struct messaging_context *msg_ctx,
7804                                                        const char *servername,
7805                                                        const char *architecture,
7806                                                        uint32_t level,
7807                                                        union spoolss_DriverInfo **info_p,
7808                                                        uint32_t *count_p)
7809 {
7810         int i;
7811         uint32_t version;
7812         struct spoolss_DriverInfo8 *driver;
7813         union spoolss_DriverInfo *info = NULL;
7814         uint32_t count = 0;
7815         WERROR result = WERR_OK;
7816         uint32_t num_drivers;
7817         const char **drivers;
7818         struct dcerpc_binding_handle *b;
7819         TALLOC_CTX *tmp_ctx = NULL;
7820
7821         *count_p = 0;
7822         *info_p = NULL;
7823
7824         tmp_ctx = talloc_new(mem_ctx);
7825         if (!tmp_ctx) {
7826                 return WERR_NOT_ENOUGH_MEMORY;
7827         }
7828
7829         result = winreg_printer_binding_handle(tmp_ctx,
7830                                                session_info,
7831                                                msg_ctx,
7832                                                &b);
7833         if (!W_ERROR_IS_OK(result)) {
7834                 goto out;
7835         }
7836
7837         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7838                 result = winreg_get_driver_list(tmp_ctx, b,
7839                                                 architecture, version,
7840                                                 &num_drivers, &drivers);
7841                 if (!W_ERROR_IS_OK(result)) {
7842                         goto out;
7843                 }
7844                 DEBUG(4, ("we have:[%d] drivers in environment"
7845                           " [%s] and version [%d]\n",
7846                           num_drivers, architecture, version));
7847
7848                 if (num_drivers != 0) {
7849                         info = talloc_realloc(tmp_ctx, info,
7850                                                     union spoolss_DriverInfo,
7851                                                     count + num_drivers);
7852                         if (!info) {
7853                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7854                                         "failed to enlarge driver info buffer!\n"));
7855                                 result = WERR_NOT_ENOUGH_MEMORY;
7856                                 goto out;
7857                         }
7858                 }
7859
7860                 for (i = 0; i < num_drivers; i++) {
7861                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7862
7863                         result = winreg_get_driver(tmp_ctx, b,
7864                                                    architecture, drivers[i],
7865                                                    version, &driver);
7866                         if (!W_ERROR_IS_OK(result)) {
7867                                 goto out;
7868                         }
7869
7870                         switch (level) {
7871                         case 1:
7872                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7873                                                                    driver, servername);
7874                                 break;
7875                         case 2:
7876                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7877                                                                    driver, servername);
7878                                 break;
7879                         case 3:
7880                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7881                                                                    driver, servername);
7882                                 break;
7883                         case 4:
7884                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7885                                                                    driver, servername);
7886                                 break;
7887                         case 5:
7888                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7889                                                                    driver, servername);
7890                                 break;
7891                         case 6:
7892                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7893                                                                    driver, servername);
7894                                 break;
7895                         case 8:
7896                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7897                                                                    driver, servername);
7898                                 break;
7899                         default:
7900                                 result = WERR_INVALID_LEVEL;
7901                                 break;
7902                         }
7903
7904                         TALLOC_FREE(driver);
7905
7906                         if (!W_ERROR_IS_OK(result)) {
7907                                 goto out;
7908                         }
7909                 }
7910
7911                 count += num_drivers;
7912                 TALLOC_FREE(drivers);
7913         }
7914
7915 out:
7916         if (W_ERROR_IS_OK(result)) {
7917                 *info_p = talloc_move(mem_ctx, &info);
7918                 *count_p = count;
7919         }
7920
7921         talloc_free(tmp_ctx);
7922         return result;
7923 }
7924
7925 /****************************************************************************
7926  Enumerates all printer drivers by level.
7927 ****************************************************************************/
7928
7929 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7930                                        const struct auth_session_info *session_info,
7931                                        struct messaging_context *msg_ctx,
7932                                        const char *servername,
7933                                        const char *architecture,
7934                                        uint32_t level,
7935                                        union spoolss_DriverInfo **info_p,
7936                                        uint32_t *count_p)
7937 {
7938         uint32_t a,i;
7939         WERROR result = WERR_OK;
7940
7941         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7942
7943                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7944
7945                         union spoolss_DriverInfo *info = NULL;
7946                         uint32_t count = 0;
7947
7948                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7949                                                                           session_info,
7950                                                                           msg_ctx,
7951                                                                           servername,
7952                                                                           archi_table[a].long_archi,
7953                                                                           level,
7954                                                                           &info,
7955                                                                           &count);
7956                         if (!W_ERROR_IS_OK(result)) {
7957                                 continue;
7958                         }
7959
7960                         for (i=0; i < count; i++) {
7961                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7962                                              info[i], info_p, count_p);
7963                         }
7964                 }
7965
7966                 return result;
7967         }
7968
7969         return enumprinterdrivers_level_by_architecture(mem_ctx,
7970                                                         session_info,
7971                                                         msg_ctx,
7972                                                         servername,
7973                                                         architecture,
7974                                                         level,
7975                                                         info_p,
7976                                                         count_p);
7977 }
7978
7979 /****************************************************************
7980  _spoolss_EnumPrinterDrivers
7981 ****************************************************************/
7982
7983 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7984                                    struct spoolss_EnumPrinterDrivers *r)
7985 {
7986         const char *cservername;
7987         WERROR result;
7988
7989         /* that's an [in out] buffer */
7990
7991         if (!r->in.buffer && (r->in.offered != 0)) {
7992                 return WERR_INVALID_PARAMETER;
7993         }
7994
7995         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7996
7997         *r->out.needed = 0;
7998         *r->out.count = 0;
7999         *r->out.info = NULL;
8000
8001         cservername = canon_servername(r->in.server);
8002
8003         if (!is_myname_or_ipaddr(cservername)) {
8004                 return WERR_UNKNOWN_PRINTER_DRIVER;
8005         }
8006
8007         result = enumprinterdrivers_level(p->mem_ctx,
8008                                           get_session_info_system(),
8009                                           p->msg_ctx,
8010                                           cservername,
8011                                           r->in.environment,
8012                                           r->in.level,
8013                                           r->out.info,
8014                                           r->out.count);
8015         if (!W_ERROR_IS_OK(result)) {
8016                 return result;
8017         }
8018
8019         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8020                                                      spoolss_EnumPrinterDrivers,
8021                                                      *r->out.info, r->in.level,
8022                                                      *r->out.count);
8023         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8024         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8025
8026         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8027 }
8028
8029 /****************************************************************
8030  _spoolss_EnumForms
8031 ****************************************************************/
8032
8033 WERROR _spoolss_EnumForms(struct pipes_struct *p,
8034                           struct spoolss_EnumForms *r)
8035 {
8036         WERROR result;
8037
8038         *r->out.count = 0;
8039         *r->out.needed = 0;
8040         *r->out.info = NULL;
8041
8042         /* that's an [in out] buffer */
8043
8044         if (!r->in.buffer && (r->in.offered != 0) ) {
8045                 return WERR_INVALID_PARAMETER;
8046         }
8047
8048         DEBUG(4,("_spoolss_EnumForms\n"));
8049         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8050         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
8051
8052         switch (r->in.level) {
8053         case 1:
8054                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
8055                                                    get_session_info_system(),
8056                                                    p->msg_ctx,
8057                                                    r->out.count,
8058                                                    r->out.info);
8059                 break;
8060         default:
8061                 result = WERR_INVALID_LEVEL;
8062                 break;
8063         }
8064
8065         if (!W_ERROR_IS_OK(result)) {
8066                 return result;
8067         }
8068
8069         if (*r->out.count == 0) {
8070                 return WERR_NO_MORE_ITEMS;
8071         }
8072
8073         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8074                                                      spoolss_EnumForms,
8075                                                      *r->out.info, r->in.level,
8076                                                      *r->out.count);
8077         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8078         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8079
8080         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8081 }
8082
8083 /****************************************************************
8084  _spoolss_GetForm
8085 ****************************************************************/
8086
8087 WERROR _spoolss_GetForm(struct pipes_struct *p,
8088                         struct spoolss_GetForm *r)
8089 {
8090         WERROR result;
8091
8092         /* that's an [in out] buffer */
8093
8094         if (!r->in.buffer && (r->in.offered != 0)) {
8095                 TALLOC_FREE(r->out.info);
8096                 return WERR_INVALID_PARAMETER;
8097         }
8098
8099         DEBUG(4,("_spoolss_GetForm\n"));
8100         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8101         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
8102
8103         switch (r->in.level) {
8104         case 1:
8105                 result = winreg_printer_getform1_internal(p->mem_ctx,
8106                                                  get_session_info_system(),
8107                                                  p->msg_ctx,
8108                                                  r->in.form_name,
8109                                                  &r->out.info->info1);
8110                 break;
8111         default:
8112                 result = WERR_INVALID_LEVEL;
8113                 break;
8114         }
8115
8116         if (!W_ERROR_IS_OK(result)) {
8117                 TALLOC_FREE(r->out.info);
8118                 return result;
8119         }
8120
8121         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8122                                                r->out.info, r->in.level);
8123         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8124
8125         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8126 }
8127
8128 /****************************************************************************
8129 ****************************************************************************/
8130
8131 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8132                           struct spoolss_PortInfo1 *r,
8133                           const char *name)
8134 {
8135         r->port_name = talloc_strdup(mem_ctx, name);
8136         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8137
8138         return WERR_OK;
8139 }
8140
8141 /****************************************************************************
8142  TODO: This probably needs distinguish between TCP/IP and Local ports
8143  somehow.
8144 ****************************************************************************/
8145
8146 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8147                           struct spoolss_PortInfo2 *r,
8148                           const char *name)
8149 {
8150         r->port_name = talloc_strdup(mem_ctx, name);
8151         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8152
8153         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8154         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8155
8156         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8157         W_ERROR_HAVE_NO_MEMORY(r->description);
8158
8159         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8160         r->reserved = 0;
8161
8162         return WERR_OK;
8163 }
8164
8165
8166 /****************************************************************************
8167  wrapper around the enumer ports command
8168 ****************************************************************************/
8169
8170 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8171 {
8172         char *cmd = lp_enumports_command(talloc_tos());
8173         char **qlines = NULL;
8174         char *command = NULL;
8175         int numlines;
8176         int ret;
8177         int fd;
8178
8179         *count = 0;
8180         *lines = NULL;
8181
8182         /* if no hook then just fill in the default port */
8183
8184         if ( !*cmd ) {
8185                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8186                         return WERR_NOT_ENOUGH_MEMORY;
8187                 }
8188                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8189                         TALLOC_FREE(qlines);
8190                         return WERR_NOT_ENOUGH_MEMORY;
8191                 }
8192                 qlines[1] = NULL;
8193                 numlines = 1;
8194         }
8195         else {
8196                 /* we have a valid enumport command */
8197
8198                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8199                 if (!command) {
8200                         return WERR_NOT_ENOUGH_MEMORY;
8201                 }
8202
8203                 DEBUG(10,("Running [%s]\n", command));
8204                 ret = smbrun(command, &fd, NULL);
8205                 DEBUG(10,("Returned [%d]\n", ret));
8206                 TALLOC_FREE(command);
8207                 if (ret != 0) {
8208                         if (fd != -1) {
8209                                 close(fd);
8210                         }
8211                         return WERR_ACCESS_DENIED;
8212                 }
8213
8214                 numlines = 0;
8215                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
8216                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8217                 close(fd);
8218         }
8219
8220         *count = numlines;
8221         *lines = qlines;
8222
8223         return WERR_OK;
8224 }
8225
8226 /****************************************************************************
8227  enumports level 1.
8228 ****************************************************************************/
8229
8230 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8231                                 union spoolss_PortInfo **info_p,
8232                                 uint32_t *count)
8233 {
8234         union spoolss_PortInfo *info = NULL;
8235         int i=0;
8236         WERROR result = WERR_OK;
8237         char **qlines = NULL;
8238         int numlines = 0;
8239
8240         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8241         if (!W_ERROR_IS_OK(result)) {
8242                 goto out;
8243         }
8244
8245         if (numlines) {
8246                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8247                 if (!info) {
8248                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8249                         result = WERR_NOT_ENOUGH_MEMORY;
8250                         goto out;
8251                 }
8252
8253                 for (i=0; i<numlines; i++) {
8254                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8255                         result = fill_port_1(info, &info[i].info1, qlines[i]);
8256                         if (!W_ERROR_IS_OK(result)) {
8257                                 goto out;
8258                         }
8259                 }
8260         }
8261         TALLOC_FREE(qlines);
8262
8263 out:
8264         if (!W_ERROR_IS_OK(result)) {
8265                 TALLOC_FREE(info);
8266                 TALLOC_FREE(qlines);
8267                 *count = 0;
8268                 *info_p = NULL;
8269                 return result;
8270         }
8271
8272         *info_p = info;
8273         *count = numlines;
8274
8275         return WERR_OK;
8276 }
8277
8278 /****************************************************************************
8279  enumports level 2.
8280 ****************************************************************************/
8281
8282 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8283                                 union spoolss_PortInfo **info_p,
8284                                 uint32_t *count)
8285 {
8286         union spoolss_PortInfo *info = NULL;
8287         int i=0;
8288         WERROR result = WERR_OK;
8289         char **qlines = NULL;
8290         int numlines = 0;
8291
8292         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8293         if (!W_ERROR_IS_OK(result)) {
8294                 goto out;
8295         }
8296
8297         if (numlines) {
8298                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8299                 if (!info) {
8300                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8301                         result = WERR_NOT_ENOUGH_MEMORY;
8302                         goto out;
8303                 }
8304
8305                 for (i=0; i<numlines; i++) {
8306                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8307                         result = fill_port_2(info, &info[i].info2, qlines[i]);
8308                         if (!W_ERROR_IS_OK(result)) {
8309                                 goto out;
8310                         }
8311                 }
8312         }
8313         TALLOC_FREE(qlines);
8314
8315 out:
8316         if (!W_ERROR_IS_OK(result)) {
8317                 TALLOC_FREE(info);
8318                 TALLOC_FREE(qlines);
8319                 *count = 0;
8320                 *info_p = NULL;
8321                 return result;
8322         }
8323
8324         *info_p = info;
8325         *count = numlines;
8326
8327         return WERR_OK;
8328 }
8329
8330 /****************************************************************
8331  _spoolss_EnumPorts
8332 ****************************************************************/
8333
8334 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8335                           struct spoolss_EnumPorts *r)
8336 {
8337         WERROR result;
8338
8339         /* that's an [in out] buffer */
8340
8341         if (!r->in.buffer && (r->in.offered != 0)) {
8342                 return WERR_INVALID_PARAMETER;
8343         }
8344
8345         DEBUG(4,("_spoolss_EnumPorts\n"));
8346
8347         *r->out.count = 0;
8348         *r->out.needed = 0;
8349         *r->out.info = NULL;
8350
8351         switch (r->in.level) {
8352         case 1:
8353                 result = enumports_level_1(p->mem_ctx, r->out.info,
8354                                            r->out.count);
8355                 break;
8356         case 2:
8357                 result = enumports_level_2(p->mem_ctx, r->out.info,
8358                                            r->out.count);
8359                 break;
8360         default:
8361                 return WERR_INVALID_LEVEL;
8362         }
8363
8364         if (!W_ERROR_IS_OK(result)) {
8365                 return result;
8366         }
8367
8368         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8369                                                      spoolss_EnumPorts,
8370                                                      *r->out.info, r->in.level,
8371                                                      *r->out.count);
8372         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8373         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8374
8375         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8376 }
8377
8378 /****************************************************************************
8379 ****************************************************************************/
8380
8381 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8382                                            const char *server,
8383                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8384                                            struct spoolss_DeviceMode *devmode,
8385                                            struct security_descriptor *secdesc,
8386                                            struct spoolss_UserLevelCtr *user_ctr,
8387                                            struct policy_handle *handle)
8388 {
8389         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8390         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8391         int     snum;
8392         WERROR err = WERR_OK;
8393
8394         /* samba does not have a concept of local, non-shared printers yet, so
8395          * make sure we always setup sharename - gd */
8396         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8397             (info2->printername != NULL && info2->printername[0] != '\0')) {
8398                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8399                         "no sharename has been set, setting printername %s as sharename\n",
8400                         info2->printername));
8401                 info2->sharename = info2->printername;
8402         }
8403
8404         /* check to see if the printer already exists */
8405         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8406                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8407                         info2->sharename));
8408                 return WERR_PRINTER_ALREADY_EXISTS;
8409         }
8410
8411         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8412                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8413                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8414                                 info2->printername));
8415                         return WERR_PRINTER_ALREADY_EXISTS;
8416                 }
8417         }
8418
8419         /* validate printer info struct */
8420         if (!info2->printername || strlen(info2->printername) == 0) {
8421                 return WERR_INVALID_PRINTER_NAME;
8422         }
8423         if (!info2->portname || strlen(info2->portname) == 0) {
8424                 return WERR_UNKNOWN_PORT;
8425         }
8426         if (!info2->drivername || strlen(info2->drivername) == 0) {
8427                 return WERR_UNKNOWN_PRINTER_DRIVER;
8428         }
8429         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8430                 return WERR_UNKNOWN_PRINTPROCESSOR;
8431         }
8432
8433         /* FIXME!!!  smbd should check to see if the driver is installed before
8434            trying to add a printer like this  --jerry */
8435
8436         if (*lp_addprinter_command(talloc_tos()) ) {
8437                 char *raddr;
8438
8439                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8440                                                          p->mem_ctx);
8441                 if (raddr == NULL) {
8442                         return WERR_NOT_ENOUGH_MEMORY;
8443                 }
8444
8445                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8446                                        info2, raddr,
8447                                        p->msg_ctx) ) {
8448                         return WERR_ACCESS_DENIED;
8449                 }
8450         } else {
8451                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8452                         "smb.conf parameter \"addprinter command\" is defined. This "
8453                         "parameter must exist for this call to succeed\n",
8454                         info2->sharename ));
8455         }
8456
8457         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8458                 return WERR_ACCESS_DENIED;
8459         }
8460
8461         /* you must be a printer admin to add a new printer */
8462         if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8463                                               p->msg_ctx,
8464                                               snum,
8465                                               PRINTER_ACCESS_ADMINISTER))) {
8466                 return WERR_ACCESS_DENIED;
8467         }
8468
8469         /*
8470          * Do sanity check on the requested changes for Samba.
8471          */
8472
8473         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8474                 return WERR_INVALID_PARAMETER;
8475         }
8476
8477         if (devmode == NULL) {
8478                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8479         }
8480
8481         err = update_dsspooler(p->mem_ctx,
8482                                get_session_info_system(),
8483                                p->msg_ctx,
8484                                0,
8485                                info2,
8486                                NULL);
8487         if (!W_ERROR_IS_OK(err)) {
8488                 return err;
8489         }
8490
8491         err = winreg_update_printer_internal(p->mem_ctx,
8492                                     get_session_info_system(),
8493                                     p->msg_ctx,
8494                                     info2->sharename,
8495                                     info2_mask,
8496                                     info2,
8497                                     devmode,
8498                                     secdesc);
8499         if (!W_ERROR_IS_OK(err)) {
8500                 return err;
8501         }
8502
8503         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8504         if (!W_ERROR_IS_OK(err)) {
8505                 /* Handle open failed - remove addition. */
8506                 ZERO_STRUCTP(handle);
8507                 return err;
8508         }
8509
8510         return WERR_OK;
8511 }
8512
8513 /****************************************************************
8514  _spoolss_AddPrinterEx
8515 ****************************************************************/
8516
8517 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8518                              struct spoolss_AddPrinterEx *r)
8519 {
8520         switch (r->in.info_ctr->level) {
8521         case 1:
8522                 /* we don't handle yet */
8523                 /* but I know what to do ... */
8524                 return WERR_INVALID_LEVEL;
8525         case 2:
8526                 return spoolss_addprinterex_level_2(p, r->in.server,
8527                                                     r->in.info_ctr,
8528                                                     r->in.devmode_ctr->devmode,
8529                                                     r->in.secdesc_ctr->sd,
8530                                                     r->in.userlevel_ctr,
8531                                                     r->out.handle);
8532         default:
8533                 return WERR_INVALID_LEVEL;
8534         }
8535 }
8536
8537 /****************************************************************
8538  _spoolss_AddPrinter
8539 ****************************************************************/
8540
8541 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8542                            struct spoolss_AddPrinter *r)
8543 {
8544         struct spoolss_AddPrinterEx a;
8545         struct spoolss_UserLevelCtr userlevel_ctr;
8546
8547         ZERO_STRUCT(userlevel_ctr);
8548
8549         userlevel_ctr.level = 1;
8550
8551         a.in.server             = r->in.server;
8552         a.in.info_ctr           = r->in.info_ctr;
8553         a.in.devmode_ctr        = r->in.devmode_ctr;
8554         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8555         a.in.userlevel_ctr      = &userlevel_ctr;
8556         a.out.handle            = r->out.handle;
8557
8558         return _spoolss_AddPrinterEx(p, &a);
8559 }
8560
8561 /****************************************************************
8562  _spoolss_AddPrinterDriverEx
8563 ****************************************************************/
8564
8565 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8566                                    struct spoolss_AddPrinterDriverEx *r)
8567 {
8568         WERROR err = WERR_OK;
8569         const char *driver_name = NULL;
8570         const char *driver_directory = NULL;
8571         uint32_t version;
8572
8573         /*
8574          * we only support the semantics of AddPrinterDriver()
8575          * i.e. only copy files that are newer than existing ones
8576          */
8577
8578         if (r->in.flags == 0) {
8579                 return WERR_INVALID_PARAMETER;
8580         }
8581
8582         if (!(r->in.flags & APD_COPY_ALL_FILES) &&
8583             !(r->in.flags & APD_COPY_NEW_FILES)) {
8584                 return WERR_ACCESS_DENIED;
8585         }
8586
8587         /* FIXME */
8588         if (r->in.info_ctr->level != 3 &&
8589             r->in.info_ctr->level != 6 &&
8590             r->in.info_ctr->level != 8) {
8591                 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8592                         r->in.info_ctr->level));
8593                 return WERR_INVALID_LEVEL;
8594         }
8595
8596         DEBUG(5,("Cleaning driver's information\n"));
8597         err = clean_up_driver_struct(p->mem_ctx,
8598                                      p->session_info,
8599                                      r->in.info_ctr,
8600                                      r->in.flags,
8601                                      &driver_directory);
8602         if (!W_ERROR_IS_OK(err)) {
8603                 DBG_ERR("clean_up_driver_struct failed - %s\n",
8604                         win_errstr(err));
8605                 goto done;
8606         }
8607
8608         DEBUG(5,("Moving driver to final destination\n"));
8609         err = move_driver_to_download_area(p->session_info,
8610                                            r->in.info_ctr,
8611                                            driver_directory);
8612         if (!W_ERROR_IS_OK(err)) {
8613                 DBG_ERR("move_driver_to_download_area failed - %s\n",
8614                         win_errstr(err));
8615                 goto done;
8616         }
8617
8618         err = winreg_add_driver_internal(p->mem_ctx,
8619                                 get_session_info_system(),
8620                                 p->msg_ctx,
8621                                 r->in.info_ctr,
8622                                 &driver_name,
8623                                 &version);
8624         if (!W_ERROR_IS_OK(err)) {
8625                 DBG_ERR("winreg_add_driver_internal failed - %s\n",
8626                         win_errstr(err));
8627                 goto done;
8628         }
8629
8630         /*
8631          * I think this is where he DrvUpgradePrinter() hook would be
8632          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8633          * server.  Right now, we just need to send ourselves a message
8634          * to update each printer bound to this driver.   --jerry
8635          */
8636
8637         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8638                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8639                         __func__, driver_name));
8640         }
8641
8642 done:
8643         return err;
8644 }
8645
8646 /****************************************************************
8647  _spoolss_AddPrinterDriver
8648 ****************************************************************/
8649
8650 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8651                                  struct spoolss_AddPrinterDriver *r)
8652 {
8653         struct spoolss_AddPrinterDriverEx a;
8654
8655         switch (r->in.info_ctr->level) {
8656         case 2:
8657         case 3:
8658         case 4:
8659         case 5:
8660                 break;
8661         default:
8662                 return WERR_INVALID_LEVEL;
8663         }
8664
8665         a.in.servername         = r->in.servername;
8666         a.in.info_ctr           = r->in.info_ctr;
8667         a.in.flags              = APD_COPY_NEW_FILES;
8668
8669         return _spoolss_AddPrinterDriverEx(p, &a);
8670 }
8671
8672 /****************************************************************************
8673 ****************************************************************************/
8674
8675 struct _spoolss_paths {
8676         int type;
8677         const char *share;
8678         const char *dir;
8679 };
8680
8681 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8682
8683 static const struct _spoolss_paths spoolss_paths[]= {
8684         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8685         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8686 };
8687
8688 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8689                                           const char *servername,
8690                                           const char *environment,
8691                                           int component,
8692                                           char **path)
8693 {
8694         const char *pservername = NULL;
8695         const char *long_archi;
8696         const char *short_archi;
8697
8698         *path = NULL;
8699
8700         /* environment may be empty */
8701         if (environment && strlen(environment)) {
8702                 long_archi = environment;
8703         } else {
8704                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8705                                                   "spoolss", "architecture",
8706                                                   GLOBAL_SPOOLSS_ARCHITECTURE);
8707         }
8708
8709         /* servername may be empty */
8710         if (servername && strlen(servername)) {
8711                 pservername = canon_servername(servername);
8712
8713                 if (!is_myname_or_ipaddr(pservername)) {
8714                         return WERR_INVALID_PARAMETER;
8715                 }
8716         }
8717
8718         if (!(short_archi = get_short_archi(long_archi))) {
8719                 return WERR_INVALID_ENVIRONMENT;
8720         }
8721
8722         switch (component) {
8723         case SPOOLSS_PRTPROCS_PATH:
8724         case SPOOLSS_DRIVER_PATH:
8725                 if (pservername) {
8726                         *path = talloc_asprintf(mem_ctx,
8727                                         "\\\\%s\\%s\\%s",
8728                                         pservername,
8729                                         spoolss_paths[component].share,
8730                                         short_archi);
8731                 } else {
8732                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8733                                         SPOOLSS_DEFAULT_SERVER_PATH,
8734                                         spoolss_paths[component].dir,
8735                                         short_archi);
8736                 }
8737                 break;
8738         default:
8739                 return WERR_INVALID_PARAMETER;
8740         }
8741
8742         if (!*path) {
8743                 return WERR_NOT_ENOUGH_MEMORY;
8744         }
8745
8746         return WERR_OK;
8747 }
8748
8749 /****************************************************************************
8750 ****************************************************************************/
8751
8752 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8753                                           const char *servername,
8754                                           const char *environment,
8755                                           struct spoolss_DriverDirectoryInfo1 *r)
8756 {
8757         WERROR werr;
8758         char *path = NULL;
8759
8760         werr = compose_spoolss_server_path(mem_ctx,
8761                                            servername,
8762                                            environment,
8763                                            SPOOLSS_DRIVER_PATH,
8764                                            &path);
8765         if (!W_ERROR_IS_OK(werr)) {
8766                 return werr;
8767         }
8768
8769         DEBUG(4,("printer driver directory: [%s]\n", path));
8770
8771         r->directory_name = path;
8772
8773         return WERR_OK;
8774 }
8775
8776 /****************************************************************
8777  _spoolss_GetPrinterDriverDirectory
8778 ****************************************************************/
8779
8780 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8781                                           struct spoolss_GetPrinterDriverDirectory *r)
8782 {
8783         WERROR werror;
8784
8785         /* that's an [in out] buffer */
8786
8787         if (!r->in.buffer && (r->in.offered != 0)) {
8788                 TALLOC_FREE(r->out.info);
8789                 return WERR_INVALID_PARAMETER;
8790         }
8791
8792         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8793                 r->in.level));
8794
8795         *r->out.needed = 0;
8796
8797         /* r->in.level is ignored */
8798
8799         werror = getprinterdriverdir_level_1(p->mem_ctx,
8800                                              r->in.server,
8801                                              r->in.environment,
8802                                              &r->out.info->info1);
8803         if (!W_ERROR_IS_OK(werror)) {
8804                 TALLOC_FREE(r->out.info);
8805                 return werror;
8806         }
8807
8808         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8809                                                r->out.info, r->in.level);
8810         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8811
8812         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8813 }
8814
8815 /****************************************************************
8816  _spoolss_EnumPrinterData
8817 ****************************************************************/
8818
8819 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8820                                 struct spoolss_EnumPrinterData *r)
8821 {
8822         WERROR result;
8823         struct spoolss_EnumPrinterDataEx r2;
8824         uint32_t count;
8825         struct spoolss_PrinterEnumValues *info, *val = NULL;
8826         uint32_t needed;
8827
8828         r2.in.handle    = r->in.handle;
8829         r2.in.key_name  = "PrinterDriverData";
8830         r2.in.offered   = 0;
8831         r2.out.count    = &count;
8832         r2.out.info     = &info;
8833         r2.out.needed   = &needed;
8834
8835         result = _spoolss_EnumPrinterDataEx(p, &r2);
8836         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8837                 r2.in.offered = needed;
8838                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8839         }
8840         if (!W_ERROR_IS_OK(result)) {
8841                 return result;
8842         }
8843
8844         /*
8845          * The NT machine wants to know the biggest size of value and data
8846          *
8847          * cf: MSDN EnumPrinterData remark section
8848          */
8849
8850         if (!r->in.value_offered && !r->in.data_offered) {
8851                 uint32_t biggest_valuesize = 0;
8852                 uint32_t biggest_datasize = 0;
8853                 int i, name_length;
8854
8855                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8856
8857                 for (i=0; i<count; i++) {
8858
8859                         name_length = strlen(info[i].value_name);
8860                         if (strlen(info[i].value_name) > biggest_valuesize) {
8861                                 biggest_valuesize = name_length;
8862                         }
8863
8864                         if (info[i].data_length > biggest_datasize) {
8865                                 biggest_datasize = info[i].data_length;
8866                         }
8867
8868                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8869                                 biggest_datasize));
8870                 }
8871
8872                 /* the value is an UNICODE string but real_value_size is the length
8873                    in bytes including the trailing 0 */
8874
8875                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8876                 *r->out.data_needed  = biggest_datasize;
8877
8878                 DEBUG(6,("final values: [%d], [%d]\n",
8879                         *r->out.value_needed, *r->out.data_needed));
8880
8881                 return WERR_OK;
8882         }
8883
8884         if (r->in.enum_index < count) {
8885                 val = &info[r->in.enum_index];
8886         }
8887
8888         if (val == NULL) {
8889                 /* out_value should default to "" or else NT4 has
8890                    problems unmarshalling the response */
8891
8892                 if (r->in.value_offered) {
8893                         *r->out.value_needed = 1;
8894                         r->out.value_name = talloc_strdup(r, "");
8895                         if (!r->out.value_name) {
8896                                 return WERR_NOT_ENOUGH_MEMORY;
8897                         }
8898                 } else {
8899                         r->out.value_name = NULL;
8900                         *r->out.value_needed = 0;
8901                 }
8902
8903                 /* the data is counted in bytes */
8904
8905                 *r->out.data_needed = r->in.data_offered;
8906
8907                 result = WERR_NO_MORE_ITEMS;
8908         } else {
8909                 /*
8910                  * the value is:
8911                  * - counted in bytes in the request
8912                  * - counted in UNICODE chars in the max reply
8913                  * - counted in bytes in the real size
8914                  *
8915                  * take a pause *before* coding not *during* coding
8916                  */
8917
8918                 /* name */
8919                 if (r->in.value_offered) {
8920                         r->out.value_name = talloc_strdup(r, val->value_name);
8921                         if (!r->out.value_name) {
8922                                 return WERR_NOT_ENOUGH_MEMORY;
8923                         }
8924                         *r->out.value_needed = val->value_name_len;
8925                 } else {
8926                         r->out.value_name = NULL;
8927                         *r->out.value_needed = 0;
8928                 }
8929
8930                 /* type */
8931
8932                 *r->out.type = val->type;
8933
8934                 /* data - counted in bytes */
8935
8936                 /*
8937                  * See the section "Dynamically Typed Query Parameters"
8938                  * in MS-RPRN.
8939                  */
8940
8941                 if (r->out.data && val->data && val->data->data &&
8942                                 val->data_length && r->in.data_offered) {
8943                         memcpy(r->out.data, val->data->data,
8944                                 MIN(val->data_length,r->in.data_offered));
8945                 }
8946
8947                 *r->out.data_needed = val->data_length;
8948
8949                 result = WERR_OK;
8950         }
8951
8952         return result;
8953 }
8954
8955 /****************************************************************
8956  _spoolss_SetPrinterData
8957 ****************************************************************/
8958
8959 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8960                                struct spoolss_SetPrinterData *r)
8961 {
8962         struct spoolss_SetPrinterDataEx r2;
8963
8964         r2.in.handle            = r->in.handle;
8965         r2.in.key_name          = "PrinterDriverData";
8966         r2.in.value_name        = r->in.value_name;
8967         r2.in.type              = r->in.type;
8968         r2.in.data              = r->in.data;
8969         r2.in.offered           = r->in.offered;
8970
8971         return _spoolss_SetPrinterDataEx(p, &r2);
8972 }
8973
8974 /****************************************************************
8975  _spoolss_ResetPrinter
8976 ****************************************************************/
8977
8978 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8979                              struct spoolss_ResetPrinter *r)
8980 {
8981         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8982         int             snum;
8983
8984         DEBUG(5,("_spoolss_ResetPrinter\n"));
8985
8986         /*
8987          * All we do is to check to see if the handle and queue is valid.
8988          * This call really doesn't mean anything to us because we only
8989          * support RAW printing.   --jerry
8990          */
8991
8992         if (!Printer) {
8993                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8994                         OUR_HANDLE(r->in.handle)));
8995                 return WERR_INVALID_HANDLE;
8996         }
8997
8998         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8999                 return WERR_INVALID_HANDLE;
9000
9001
9002         /* blindly return success */
9003         return WERR_OK;
9004 }
9005
9006 /****************************************************************
9007  _spoolss_DeletePrinterData
9008 ****************************************************************/
9009
9010 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
9011                                   struct spoolss_DeletePrinterData *r)
9012 {
9013         struct spoolss_DeletePrinterDataEx r2;
9014
9015         r2.in.handle            = r->in.handle;
9016         r2.in.key_name          = "PrinterDriverData";
9017         r2.in.value_name        = r->in.value_name;
9018
9019         return _spoolss_DeletePrinterDataEx(p, &r2);
9020 }
9021
9022 /****************************************************************
9023  _spoolss_AddForm
9024 ****************************************************************/
9025
9026 WERROR _spoolss_AddForm(struct pipes_struct *p,
9027                         struct spoolss_AddForm *r)
9028 {
9029         struct spoolss_AddFormInfo1 *form;
9030         int snum = -1;
9031         WERROR status = WERR_OK;
9032         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9033         struct dcerpc_binding_handle *b;
9034         TALLOC_CTX *tmp_ctx = NULL;
9035
9036         DEBUG(5,("_spoolss_AddForm\n"));
9037
9038         if (!Printer) {
9039                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
9040                         OUR_HANDLE(r->in.handle)));
9041                 return WERR_INVALID_HANDLE;
9042         }
9043
9044         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9045            and not a printer admin, then fail */
9046
9047         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9048             !security_token_has_privilege(p->session_info->security_token,
9049                                           SEC_PRIV_PRINT_OPERATOR)) {
9050                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
9051                 return WERR_ACCESS_DENIED;
9052         }
9053
9054         if (r->in.info_ctr->level != 1) {
9055                 return WERR_INVALID_LEVEL;
9056         }
9057
9058         form = r->in.info_ctr->info.info1;
9059         if (!form) {
9060                 return WERR_INVALID_PARAMETER;
9061         }
9062
9063         switch (form->flags) {
9064         case SPOOLSS_FORM_USER:
9065         case SPOOLSS_FORM_BUILTIN:
9066         case SPOOLSS_FORM_PRINTER:
9067                 break;
9068         default:
9069                 return WERR_INVALID_PARAMETER;
9070         }
9071
9072         tmp_ctx = talloc_new(p->mem_ctx);
9073         if (!tmp_ctx) {
9074                 return WERR_NOT_ENOUGH_MEMORY;
9075         }
9076
9077         status = winreg_printer_binding_handle(tmp_ctx,
9078                                                get_session_info_system(),
9079                                                p->msg_ctx,
9080                                                &b);
9081         if (!W_ERROR_IS_OK(status)) {
9082                 goto done;
9083         }
9084
9085         status = winreg_printer_addform1(tmp_ctx, b, form);
9086         if (!W_ERROR_IS_OK(status)) {
9087                 goto done;
9088         }
9089
9090         /*
9091          * ChangeID must always be set if this is a printer
9092          */
9093         if (Printer->printer_type == SPLHND_PRINTER) {
9094                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9095                         status = WERR_INVALID_HANDLE;
9096                         goto done;
9097                 }
9098
9099                 status = winreg_printer_update_changeid(tmp_ctx, b,
9100                                                         lp_const_servicename(snum));
9101         }
9102
9103 done:
9104         talloc_free(tmp_ctx);
9105         return status;
9106 }
9107
9108 /****************************************************************
9109  _spoolss_DeleteForm
9110 ****************************************************************/
9111
9112 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9113                            struct spoolss_DeleteForm *r)
9114 {
9115         const char *form_name = r->in.form_name;
9116         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9117         int snum = -1;
9118         WERROR status = WERR_OK;
9119         struct dcerpc_binding_handle *b;
9120         TALLOC_CTX *tmp_ctx = NULL;
9121
9122         DEBUG(5,("_spoolss_DeleteForm\n"));
9123
9124         if (!Printer) {
9125                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9126                         OUR_HANDLE(r->in.handle)));
9127                 return WERR_INVALID_HANDLE;
9128         }
9129
9130         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9131             !security_token_has_privilege(p->session_info->security_token,
9132                                           SEC_PRIV_PRINT_OPERATOR)) {
9133                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9134                 return WERR_ACCESS_DENIED;
9135         }
9136
9137         tmp_ctx = talloc_new(p->mem_ctx);
9138         if (!tmp_ctx) {
9139                 return WERR_NOT_ENOUGH_MEMORY;
9140         }
9141
9142         status = winreg_printer_binding_handle(tmp_ctx,
9143                                                get_session_info_system(),
9144                                                p->msg_ctx,
9145                                                &b);
9146         if (!W_ERROR_IS_OK(status)) {
9147                 goto done;
9148         }
9149
9150         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9151         if (!W_ERROR_IS_OK(status)) {
9152                 goto done;
9153         }
9154
9155         /*
9156          * ChangeID must always be set if this is a printer
9157          */
9158         if (Printer->printer_type == SPLHND_PRINTER) {
9159                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9160                         status = WERR_INVALID_HANDLE;
9161                         goto done;
9162                 }
9163
9164                 status = winreg_printer_update_changeid(tmp_ctx, b,
9165                                                         lp_const_servicename(snum));
9166         }
9167
9168 done:
9169         talloc_free(tmp_ctx);
9170         return status;
9171 }
9172
9173 /****************************************************************
9174  _spoolss_SetForm
9175 ****************************************************************/
9176
9177 WERROR _spoolss_SetForm(struct pipes_struct *p,
9178                         struct spoolss_SetForm *r)
9179 {
9180         struct spoolss_AddFormInfo1 *form;
9181         const char *form_name = r->in.form_name;
9182         int snum = -1;
9183         WERROR status = WERR_OK;
9184         struct dcerpc_binding_handle *b;
9185         TALLOC_CTX *tmp_ctx = NULL;
9186
9187         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9188
9189         DEBUG(5,("_spoolss_SetForm\n"));
9190
9191         if (!Printer) {
9192                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9193                         OUR_HANDLE(r->in.handle)));
9194                 return WERR_INVALID_HANDLE;
9195         }
9196
9197         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9198            and not a printer admin, then fail */
9199
9200         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9201              !security_token_has_privilege(p->session_info->security_token,
9202                                            SEC_PRIV_PRINT_OPERATOR)) {
9203                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
9204                 return WERR_ACCESS_DENIED;
9205         }
9206
9207         if (r->in.info_ctr->level != 1) {
9208                 return WERR_INVALID_LEVEL;
9209         }
9210
9211         form = r->in.info_ctr->info.info1;
9212         if (!form) {
9213                 return WERR_INVALID_PARAMETER;
9214         }
9215
9216         tmp_ctx = talloc_new(p->mem_ctx);
9217         if (!tmp_ctx) {
9218                 return WERR_NOT_ENOUGH_MEMORY;
9219         }
9220
9221         status = winreg_printer_binding_handle(tmp_ctx,
9222                                                get_session_info_system(),
9223                                                p->msg_ctx,
9224                                                &b);
9225         if (!W_ERROR_IS_OK(status)) {
9226                 goto done;
9227         }
9228
9229         status = winreg_printer_setform1(tmp_ctx, b,
9230                                          form_name,
9231                                          form);
9232         if (!W_ERROR_IS_OK(status)) {
9233                 goto done;
9234         }
9235
9236         /*
9237          * ChangeID must always be set if this is a printer
9238          */
9239         if (Printer->printer_type == SPLHND_PRINTER) {
9240                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9241                         status = WERR_INVALID_HANDLE;
9242                         goto done;
9243                 }
9244
9245                 status = winreg_printer_update_changeid(tmp_ctx, b,
9246                                                         lp_const_servicename(snum));
9247         }
9248
9249 done:
9250         talloc_free(tmp_ctx);
9251         return status;
9252 }
9253
9254 /****************************************************************************
9255  fill_print_processor1
9256 ****************************************************************************/
9257
9258 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9259                                     struct spoolss_PrintProcessorInfo1 *r,
9260                                     const char *print_processor_name)
9261 {
9262         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9263         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9264
9265         return WERR_OK;
9266 }
9267
9268 /****************************************************************************
9269  enumprintprocessors level 1.
9270 ****************************************************************************/
9271
9272 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9273                                           union spoolss_PrintProcessorInfo **info_p,
9274                                           uint32_t *count)
9275 {
9276         union spoolss_PrintProcessorInfo *info;
9277         WERROR result;
9278
9279         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9280         W_ERROR_HAVE_NO_MEMORY(info);
9281
9282         *count = 1;
9283
9284         result = fill_print_processor1(info, &info[0].info1, "winprint");
9285         if (!W_ERROR_IS_OK(result)) {
9286                 goto out;
9287         }
9288
9289  out:
9290         if (!W_ERROR_IS_OK(result)) {
9291                 TALLOC_FREE(info);
9292                 *count = 0;
9293                 return result;
9294         }
9295
9296         *info_p = info;
9297
9298         return WERR_OK;
9299 }
9300
9301 /****************************************************************
9302  _spoolss_EnumPrintProcessors
9303 ****************************************************************/
9304
9305 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9306                                     struct spoolss_EnumPrintProcessors *r)
9307 {
9308         WERROR result;
9309
9310         /* that's an [in out] buffer */
9311
9312         if (!r->in.buffer && (r->in.offered != 0)) {
9313                 return WERR_INVALID_PARAMETER;
9314         }
9315
9316         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9317
9318         /*
9319          * Enumerate the print processors ...
9320          *
9321          * Just reply with "winprint", to keep NT happy
9322          * and I can use my nice printer checker.
9323          */
9324
9325         *r->out.count = 0;
9326         *r->out.needed = 0;
9327         *r->out.info = NULL;
9328
9329         if (!get_short_archi(r->in.environment)) {
9330                 return WERR_INVALID_ENVIRONMENT;
9331         }
9332
9333         switch (r->in.level) {
9334         case 1:
9335                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9336                                                      r->out.count);
9337                 break;
9338         default:
9339                 return WERR_INVALID_LEVEL;
9340         }
9341
9342         if (!W_ERROR_IS_OK(result)) {
9343                 return result;
9344         }
9345
9346         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9347                                                      spoolss_EnumPrintProcessors,
9348                                                      *r->out.info, r->in.level,
9349                                                      *r->out.count);
9350         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9351         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9352
9353         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9354 }
9355
9356 /****************************************************************************
9357  fill_printprocdatatype1
9358 ****************************************************************************/
9359
9360 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9361                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9362                                       const char *name_array)
9363 {
9364         r->name_array = talloc_strdup(mem_ctx, name_array);
9365         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9366
9367         return WERR_OK;
9368 }
9369
9370 /****************************************************************************
9371  enumprintprocdatatypes level 1.
9372 ****************************************************************************/
9373
9374 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9375                                              union spoolss_PrintProcDataTypesInfo **info_p,
9376                                              uint32_t *count)
9377 {
9378         WERROR result;
9379         union spoolss_PrintProcDataTypesInfo *info;
9380
9381         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9382         W_ERROR_HAVE_NO_MEMORY(info);
9383
9384         *count = 1;
9385
9386         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9387         if (!W_ERROR_IS_OK(result)) {
9388                 goto out;
9389         }
9390
9391  out:
9392         if (!W_ERROR_IS_OK(result)) {
9393                 TALLOC_FREE(info);
9394                 *count = 0;
9395                 return result;
9396         }
9397
9398         *info_p = info;
9399
9400         return WERR_OK;
9401 }
9402
9403 /****************************************************************
9404  _spoolss_EnumPrintProcessorDataTypes
9405 ****************************************************************/
9406
9407 WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9408                                             struct spoolss_EnumPrintProcessorDataTypes *r)
9409 {
9410         WERROR result;
9411
9412         /* that's an [in out] buffer */
9413
9414         if (!r->in.buffer && (r->in.offered != 0)) {
9415                 return WERR_INVALID_PARAMETER;
9416         }
9417
9418         DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9419
9420         *r->out.count = 0;
9421         *r->out.needed = 0;
9422         *r->out.info = NULL;
9423
9424         if (r->in.print_processor_name == NULL ||
9425             !strequal(r->in.print_processor_name, "winprint")) {
9426                 return WERR_UNKNOWN_PRINTPROCESSOR;
9427         }
9428
9429         switch (r->in.level) {
9430         case 1:
9431                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9432                                                         r->out.count);
9433                 break;
9434         default:
9435                 return WERR_INVALID_LEVEL;
9436         }
9437
9438         if (!W_ERROR_IS_OK(result)) {
9439                 return result;
9440         }
9441
9442         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9443                                                      spoolss_EnumPrintProcessorDataTypes,
9444                                                      *r->out.info, r->in.level,
9445                                                      *r->out.count);
9446         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9447         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9448
9449         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9450 }
9451
9452 /****************************************************************************
9453  fill_monitor_1
9454 ****************************************************************************/
9455
9456 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9457                              struct spoolss_MonitorInfo1 *r,
9458                              const char *monitor_name)
9459 {
9460         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9461         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9462
9463         return WERR_OK;
9464 }
9465
9466 /****************************************************************************
9467  fill_monitor_2
9468 ****************************************************************************/
9469
9470 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9471                              struct spoolss_MonitorInfo2 *r,
9472                              const char *monitor_name,
9473                              const char *environment,
9474                              const char *dll_name)
9475 {
9476         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9477         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9478         r->environment                  = talloc_strdup(mem_ctx, environment);
9479         W_ERROR_HAVE_NO_MEMORY(r->environment);
9480         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9481         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9482
9483         return WERR_OK;
9484 }
9485
9486 /****************************************************************************
9487  enumprintmonitors level 1.
9488 ****************************************************************************/
9489
9490 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9491                                         union spoolss_MonitorInfo **info_p,
9492                                         uint32_t *count)
9493 {
9494         union spoolss_MonitorInfo *info;
9495         WERROR result = WERR_OK;
9496
9497         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9498         W_ERROR_HAVE_NO_MEMORY(info);
9499
9500         *count = 2;
9501
9502         result = fill_monitor_1(info, &info[0].info1,
9503                                 SPL_LOCAL_PORT);
9504         if (!W_ERROR_IS_OK(result)) {
9505                 goto out;
9506         }
9507
9508         result = fill_monitor_1(info, &info[1].info1,
9509                                 SPL_TCPIP_PORT);
9510         if (!W_ERROR_IS_OK(result)) {
9511                 goto out;
9512         }
9513
9514 out:
9515         if (!W_ERROR_IS_OK(result)) {
9516                 TALLOC_FREE(info);
9517                 *count = 0;
9518                 return result;
9519         }
9520
9521         *info_p = info;
9522
9523         return WERR_OK;
9524 }
9525
9526 /****************************************************************************
9527  enumprintmonitors level 2.
9528 ****************************************************************************/
9529
9530 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9531                                         union spoolss_MonitorInfo **info_p,
9532                                         uint32_t *count)
9533 {
9534         union spoolss_MonitorInfo *info;
9535         WERROR result = WERR_OK;
9536         const char *architecture;
9537
9538         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9539         W_ERROR_HAVE_NO_MEMORY(info);
9540
9541         *count = 2;
9542
9543         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
9544                                             "spoolss",
9545                                             "architecture",
9546                                             GLOBAL_SPOOLSS_ARCHITECTURE);
9547
9548         result = fill_monitor_2(info, &info[0].info2,
9549                                 SPL_LOCAL_PORT,
9550                                 architecture,
9551                                 "localmon.dll");
9552         if (!W_ERROR_IS_OK(result)) {
9553                 goto out;
9554         }
9555
9556         result = fill_monitor_2(info, &info[1].info2,
9557                                 SPL_TCPIP_PORT,
9558                                 architecture,
9559                                 "tcpmon.dll");
9560         if (!W_ERROR_IS_OK(result)) {
9561                 goto out;
9562         }
9563
9564 out:
9565         if (!W_ERROR_IS_OK(result)) {
9566                 TALLOC_FREE(info);
9567                 *count = 0;
9568                 return result;
9569         }
9570
9571         *info_p = info;
9572
9573         return WERR_OK;
9574 }
9575
9576 /****************************************************************
9577  _spoolss_EnumMonitors
9578 ****************************************************************/
9579
9580 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9581                              struct spoolss_EnumMonitors *r)
9582 {
9583         WERROR result;
9584
9585         /* that's an [in out] buffer */
9586
9587         if (!r->in.buffer && (r->in.offered != 0)) {
9588                 return WERR_INVALID_PARAMETER;
9589         }
9590
9591         DEBUG(5,("_spoolss_EnumMonitors\n"));
9592
9593         /*
9594          * Enumerate the print monitors ...
9595          *
9596          * Just reply with "Local Port", to keep NT happy
9597          * and I can use my nice printer checker.
9598          */
9599
9600         *r->out.count = 0;
9601         *r->out.needed = 0;
9602         *r->out.info = NULL;
9603
9604         switch (r->in.level) {
9605         case 1:
9606                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9607                                                    r->out.count);
9608                 break;
9609         case 2:
9610                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9611                                                    r->out.count);
9612                 break;
9613         default:
9614                 return WERR_INVALID_LEVEL;
9615         }
9616
9617         if (!W_ERROR_IS_OK(result)) {
9618                 return result;
9619         }
9620
9621         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9622                                                      spoolss_EnumMonitors,
9623                                                      *r->out.info, r->in.level,
9624                                                      *r->out.count);
9625         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9626         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9627
9628         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9629 }
9630
9631 /****************************************************************************
9632 ****************************************************************************/
9633
9634 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9635                              const print_queue_struct *queue,
9636                              int count, int snum,
9637                              struct spoolss_PrinterInfo2 *pinfo2,
9638                              uint32_t jobid,
9639                              int sysjob,
9640                              struct spoolss_JobInfo1 *r)
9641 {
9642         int i = 0;
9643         bool found = false;
9644
9645         for (i=0; i<count; i++) {
9646                 if (queue[i].sysjob == sysjob) {
9647                         found = true;
9648                         break;
9649                 }
9650         }
9651
9652         if (found == false) {
9653                 /* NT treats not found as bad param... yet another bad choice */
9654                 return WERR_INVALID_PARAMETER;
9655         }
9656
9657         return fill_job_info1(mem_ctx,
9658                               r,
9659                               &queue[i],
9660                               jobid,
9661                               i,
9662                               snum,
9663                               pinfo2);
9664 }
9665
9666 /****************************************************************************
9667 ****************************************************************************/
9668
9669 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9670                              const print_queue_struct *queue,
9671                              int count, int snum,
9672                              struct spoolss_PrinterInfo2 *pinfo2,
9673                              uint32_t jobid,
9674                              int sysjob,
9675                              struct spoolss_JobInfo2 *r)
9676 {
9677         int i = 0;
9678         bool found = false;
9679         struct spoolss_DeviceMode *devmode;
9680         WERROR result;
9681
9682         for (i=0; i<count; i++) {
9683                 if (queue[i].sysjob == sysjob) {
9684                         found = true;
9685                         break;
9686                 }
9687         }
9688
9689         if (found == false) {
9690                 /* NT treats not found as bad param... yet another bad
9691                    choice */
9692                 return WERR_INVALID_PARAMETER;
9693         }
9694
9695         /*
9696          * if the print job does not have a DEVMODE associated with it,
9697          * just use the one for the printer. A NULL devicemode is not
9698          *  a failure condition
9699          */
9700
9701         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9702         if (!devmode) {
9703                 result = spoolss_create_default_devmode(mem_ctx,
9704                                                 pinfo2->printername,
9705                                                 &devmode);
9706                 if (!W_ERROR_IS_OK(result)) {
9707                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9708                         return result;
9709                 }
9710         }
9711
9712         return fill_job_info2(mem_ctx,
9713                               r,
9714                               &queue[i],
9715                               jobid,
9716                               i,
9717                               snum,
9718                               pinfo2,
9719                               devmode);
9720 }
9721
9722 /****************************************************************
9723  _spoolss_GetJob
9724 ****************************************************************/
9725
9726 WERROR _spoolss_GetJob(struct pipes_struct *p,
9727                        struct spoolss_GetJob *r)
9728 {
9729         WERROR result = WERR_OK;
9730         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9731         const char *svc_name;
9732         int sysjob;
9733         int snum;
9734         int count;
9735         struct tdb_print_db *pdb;
9736         print_queue_struct      *queue = NULL;
9737         print_status_struct prt_status;
9738
9739         /* that's an [in out] buffer */
9740
9741         if (!r->in.buffer && (r->in.offered != 0)) {
9742                 result = WERR_INVALID_PARAMETER;
9743                 goto err_jinfo_free;
9744         }
9745
9746         DEBUG(5,("_spoolss_GetJob\n"));
9747
9748         *r->out.needed = 0;
9749
9750         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9751                 result = WERR_INVALID_HANDLE;
9752                 goto err_jinfo_free;
9753         }
9754
9755         svc_name = lp_const_servicename(snum);
9756         if (svc_name == NULL) {
9757                 result = WERR_INVALID_PARAMETER;
9758                 goto err_jinfo_free;
9759         }
9760
9761         result = winreg_get_printer_internal(p->mem_ctx,
9762                                     get_session_info_system(),
9763                                     p->msg_ctx,
9764                                     svc_name,
9765                                     &pinfo2);
9766         if (!W_ERROR_IS_OK(result)) {
9767                 goto err_jinfo_free;
9768         }
9769
9770         pdb = get_print_db_byname(svc_name);
9771         if (pdb == NULL) {
9772                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9773                 result = WERR_INVALID_PARAMETER;
9774                 goto err_pinfo_free;
9775         }
9776
9777         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9778         release_print_db(pdb);
9779         if (sysjob == -1) {
9780                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9781                 result = WERR_INVALID_PARAMETER;
9782                 goto err_pinfo_free;
9783         }
9784
9785         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9786
9787         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9788                      count, prt_status.status, prt_status.message));
9789
9790         switch (r->in.level) {
9791         case 1:
9792                 result = getjob_level_1(p->mem_ctx,
9793                                         queue, count, snum, pinfo2,
9794                                         r->in.job_id, sysjob,
9795                                         &r->out.info->info1);
9796                 break;
9797         case 2:
9798                 result = getjob_level_2(p->mem_ctx,
9799                                         queue, count, snum, pinfo2,
9800                                         r->in.job_id, sysjob,
9801                                         &r->out.info->info2);
9802                 break;
9803         default:
9804                 result = WERR_INVALID_LEVEL;
9805                 break;
9806         }
9807
9808         SAFE_FREE(queue);
9809         TALLOC_FREE(pinfo2);
9810
9811         if (!W_ERROR_IS_OK(result)) {
9812                 goto err_jinfo_free;
9813         }
9814
9815         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9816                                                                                    r->in.level);
9817         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9818
9819         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9820
9821 err_pinfo_free:
9822         TALLOC_FREE(pinfo2);
9823 err_jinfo_free:
9824         TALLOC_FREE(r->out.info);
9825         return result;
9826 }
9827
9828 /****************************************************************
9829  _spoolss_GetPrinterDataEx
9830 ****************************************************************/
9831
9832 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9833                                  struct spoolss_GetPrinterDataEx *r)
9834 {
9835
9836         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9837         const char *printer;
9838         int                     snum = 0;
9839         WERROR result = WERR_OK;
9840         DATA_BLOB blob;
9841         enum winreg_Type val_type = REG_NONE;
9842         uint8_t *val_data = NULL;
9843         uint32_t val_size = 0;
9844         struct dcerpc_binding_handle *b;
9845         TALLOC_CTX *tmp_ctx;
9846
9847         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9848
9849         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9850                 r->in.key_name, r->in.value_name));
9851
9852         /* in case of problem, return some default values */
9853
9854         *r->out.needed  = 0;
9855         *r->out.type    = REG_NONE;
9856
9857         tmp_ctx = talloc_new(p->mem_ctx);
9858         if (!tmp_ctx) {
9859                 return WERR_NOT_ENOUGH_MEMORY;
9860         }
9861
9862         if (!Printer) {
9863                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9864                         OUR_HANDLE(r->in.handle)));
9865                 result = WERR_INVALID_HANDLE;
9866                 goto done;
9867         }
9868
9869         /* Is the handle to a printer or to the server? */
9870
9871         if (Printer->printer_type == SPLHND_SERVER) {
9872
9873                 union spoolss_PrinterData data;
9874
9875                 result = getprinterdata_printer_server(tmp_ctx,
9876                                                        r->in.value_name,
9877                                                        r->out.type,
9878                                                        &data);
9879                 if (!W_ERROR_IS_OK(result)) {
9880                         goto done;
9881                 }
9882
9883                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9884                                                   *r->out.type, &data);
9885                 if (!W_ERROR_IS_OK(result)) {
9886                         goto done;
9887                 }
9888
9889                 *r->out.needed = blob.length;
9890
9891                 if (r->in.offered >= *r->out.needed) {
9892                         memcpy(r->out.data, blob.data, blob.length);
9893                 }
9894
9895                 result = WERR_OK;
9896                 goto done;
9897         }
9898
9899         /* check to see if the keyname is valid */
9900         if (!strlen(r->in.key_name)) {
9901                 result = WERR_INVALID_PARAMETER;
9902                 goto done;
9903         }
9904
9905         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9906                 result = WERR_INVALID_HANDLE;
9907                 goto done;
9908         }
9909         printer = lp_const_servicename(snum);
9910
9911         result = winreg_printer_binding_handle(tmp_ctx,
9912                                                get_session_info_system(),
9913                                                p->msg_ctx,
9914                                                &b);
9915         if (!W_ERROR_IS_OK(result)) {
9916                 goto done;
9917         }
9918
9919         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9920         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9921             strequal(r->in.value_name, "ChangeId")) {
9922                 *r->out.type = REG_DWORD;
9923                 *r->out.needed = 4;
9924                 if (r->in.offered >= *r->out.needed) {
9925                         uint32_t changeid = 0;
9926
9927                         result = winreg_printer_get_changeid(tmp_ctx, b,
9928                                                              printer,
9929                                                              &changeid);
9930                         if (!W_ERROR_IS_OK(result)) {
9931                                 goto done;
9932                         }
9933
9934                         SIVAL(r->out.data, 0, changeid);
9935                         result = WERR_OK;
9936                 }
9937                 goto done;
9938         }
9939
9940         result = winreg_get_printer_dataex(tmp_ctx, b,
9941                                            printer,
9942                                            r->in.key_name,
9943                                            r->in.value_name,
9944                                            &val_type,
9945                                            &val_data,
9946                                            &val_size);
9947         if (!W_ERROR_IS_OK(result)) {
9948                 goto done;
9949         }
9950
9951         *r->out.needed = val_size;
9952         *r->out.type = val_type;
9953
9954         if (r->in.offered >= *r->out.needed) {
9955                 memcpy(r->out.data, val_data, val_size);
9956         }
9957
9958 done:
9959         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9960
9961         if (W_ERROR_IS_OK(result)) {
9962                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9963         }
9964
9965         talloc_free(tmp_ctx);
9966         return result;
9967 }
9968
9969 /****************************************************************
9970  _spoolss_SetPrinterDataEx
9971 ****************************************************************/
9972
9973 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9974                                  struct spoolss_SetPrinterDataEx *r)
9975 {
9976         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9977         int                     snum = 0;
9978         WERROR                  result = WERR_OK;
9979         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9980         char                    *oid_string;
9981         struct dcerpc_binding_handle *b;
9982         TALLOC_CTX *tmp_ctx;
9983
9984         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9985
9986         /* From MSDN documentation of SetPrinterDataEx: pass request to
9987            SetPrinterData if key is "PrinterDriverData" */
9988
9989         if (!Printer) {
9990                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9991                         OUR_HANDLE(r->in.handle)));
9992                 return WERR_INVALID_HANDLE;
9993         }
9994
9995         if (Printer->printer_type == SPLHND_SERVER) {
9996                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9997                         "Not implemented for server handles yet\n"));
9998                 return WERR_INVALID_PARAMETER;
9999         }
10000
10001         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10002                 return WERR_INVALID_HANDLE;
10003         }
10004
10005         /*
10006          * Access check : NT returns "access denied" if you make a
10007          * SetPrinterData call without the necessary privildge.
10008          * we were originally returning OK if nothing changed
10009          * which made Win2k issue **a lot** of SetPrinterData
10010          * when connecting to a printer  --jerry
10011          */
10012
10013         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10014                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
10015                         "change denied by handle access permissions\n"));
10016                 return WERR_ACCESS_DENIED;
10017         }
10018
10019         tmp_ctx = talloc_new(p->mem_ctx);
10020         if (!tmp_ctx) {
10021                 return WERR_NOT_ENOUGH_MEMORY;
10022         }
10023
10024         result = winreg_printer_binding_handle(tmp_ctx,
10025                                                get_session_info_system(),
10026                                                p->msg_ctx,
10027                                                &b);
10028         if (!W_ERROR_IS_OK(result)) {
10029                 goto done;
10030         }
10031
10032         result = winreg_get_printer(tmp_ctx, b,
10033                                     lp_servicename(talloc_tos(), snum),
10034                                     &pinfo2);
10035         if (!W_ERROR_IS_OK(result)) {
10036                 goto done;
10037         }
10038
10039         /* check for OID in valuename */
10040
10041         oid_string = strchr(r->in.value_name, ',');
10042         if (oid_string) {
10043                 *oid_string = '\0';
10044                 oid_string++;
10045         }
10046
10047         /* save the registry data */
10048
10049         result = winreg_set_printer_dataex(tmp_ctx, b,
10050                                            pinfo2->sharename,
10051                                            r->in.key_name,
10052                                            r->in.value_name,
10053                                            r->in.type,
10054                                            r->in.data,
10055                                            r->in.offered);
10056
10057         if (W_ERROR_IS_OK(result)) {
10058                 /* save the OID if one was specified */
10059                 if (oid_string) {
10060                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
10061                                 r->in.key_name, SPOOL_OID_KEY);
10062                         if (!str) {
10063                                 result = WERR_NOT_ENOUGH_MEMORY;
10064                                 goto done;
10065                         }
10066
10067                         /*
10068                          * I'm not checking the status here on purpose.  Don't know
10069                          * if this is right, but I'm returning the status from the
10070                          * previous set_printer_dataex() call.  I have no idea if
10071                          * this is right.    --jerry
10072                          */
10073                         winreg_set_printer_dataex(tmp_ctx, b,
10074                                                   pinfo2->sharename,
10075                                                   str,
10076                                                   r->in.value_name,
10077                                                   REG_SZ,
10078                                                   (uint8_t *) oid_string,
10079                                                   strlen(oid_string) + 1);
10080                 }
10081
10082                 result = winreg_printer_update_changeid(tmp_ctx, b,
10083                                                         lp_const_servicename(snum));
10084
10085         }
10086
10087 done:
10088         talloc_free(tmp_ctx);
10089         return result;
10090 }
10091
10092 /****************************************************************
10093  _spoolss_DeletePrinterDataEx
10094 ****************************************************************/
10095
10096 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10097                                     struct spoolss_DeletePrinterDataEx *r)
10098 {
10099         const char *printer;
10100         int             snum=0;
10101         WERROR          status = WERR_OK;
10102         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10103
10104         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10105
10106         if (!Printer) {
10107                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10108                         "Invalid handle (%s:%u:%u).\n",
10109                         OUR_HANDLE(r->in.handle)));
10110                 return WERR_INVALID_HANDLE;
10111         }
10112
10113         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10114                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10115                         "printer properties change denied by handle\n"));
10116                 return WERR_ACCESS_DENIED;
10117         }
10118
10119         if (!r->in.value_name || !r->in.key_name) {
10120                 return WERR_NOT_ENOUGH_MEMORY;
10121         }
10122
10123         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10124                 return WERR_INVALID_HANDLE;
10125         }
10126         printer = lp_const_servicename(snum);
10127
10128         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10129                                               get_session_info_system(),
10130                                               p->msg_ctx,
10131                                               printer,
10132                                               r->in.key_name,
10133                                               r->in.value_name);
10134         if (W_ERROR_IS_OK(status)) {
10135                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
10136                                                         get_session_info_system(),
10137                                                         p->msg_ctx,
10138                                                         printer);
10139         }
10140
10141         return status;
10142 }
10143
10144 /****************************************************************
10145  _spoolss_EnumPrinterKey
10146 ****************************************************************/
10147
10148 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10149                                struct spoolss_EnumPrinterKey *r)
10150 {
10151         uint32_t        num_keys;
10152         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10153         int             snum = 0;
10154         WERROR          result = WERR_FILE_NOT_FOUND;
10155         const char **array = NULL;
10156         DATA_BLOB blob;
10157
10158         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10159
10160         if (!Printer) {
10161                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10162                         OUR_HANDLE(r->in.handle)));
10163                 return WERR_INVALID_HANDLE;
10164         }
10165
10166         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10167                 return WERR_INVALID_HANDLE;
10168         }
10169
10170         result = winreg_enum_printer_key_internal(p->mem_ctx,
10171                                          get_session_info_system(),
10172                                          p->msg_ctx,
10173                                          lp_const_servicename(snum),
10174                                          r->in.key_name,
10175                                          &num_keys,
10176                                          &array);
10177         if (!W_ERROR_IS_OK(result)) {
10178                 goto done;
10179         }
10180
10181         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10182                 result = WERR_NOT_ENOUGH_MEMORY;
10183                 goto done;
10184         }
10185
10186         *r->out._ndr_size = r->in.offered / 2;
10187         *r->out.needed = blob.length;
10188
10189         if (r->in.offered < *r->out.needed) {
10190                 result = WERR_MORE_DATA;
10191         } else {
10192                 result = WERR_OK;
10193                 r->out.key_buffer->string_array = array;
10194         }
10195
10196  done:
10197         if (!W_ERROR_IS_OK(result)) {
10198                 TALLOC_FREE(array);
10199                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10200                         *r->out.needed = 0;
10201                 }
10202         }
10203
10204         return result;
10205 }
10206
10207 /****************************************************************
10208  _spoolss_DeletePrinterKey
10209 ****************************************************************/
10210
10211 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10212                                  struct spoolss_DeletePrinterKey *r)
10213 {
10214         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10215         int                     snum=0;
10216         WERROR                  status;
10217         const char *printer;
10218         struct dcerpc_binding_handle *b;
10219         TALLOC_CTX *tmp_ctx;
10220
10221         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10222
10223         if (!Printer) {
10224                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10225                         OUR_HANDLE(r->in.handle)));
10226                 return WERR_INVALID_HANDLE;
10227         }
10228
10229         /* if keyname == NULL, return error */
10230         if ( !r->in.key_name )
10231                 return WERR_INVALID_PARAMETER;
10232
10233         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10234                 return WERR_INVALID_HANDLE;
10235         }
10236
10237         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10238                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10239                         "printer properties change denied by handle\n"));
10240                 return WERR_ACCESS_DENIED;
10241         }
10242
10243         printer = lp_const_servicename(snum);
10244
10245         tmp_ctx = talloc_new(p->mem_ctx);
10246         if (!tmp_ctx) {
10247                 return WERR_NOT_ENOUGH_MEMORY;
10248         }
10249
10250         status = winreg_printer_binding_handle(tmp_ctx,
10251                                                get_session_info_system(),
10252                                                p->msg_ctx,
10253                                                &b);
10254         if (!W_ERROR_IS_OK(status)) {
10255                 goto done;
10256         }
10257
10258         /* delete the key and all subkeys */
10259         status = winreg_delete_printer_key(tmp_ctx, b,
10260                                            printer,
10261                                            r->in.key_name);
10262         if (W_ERROR_IS_OK(status)) {
10263                 status = winreg_printer_update_changeid(tmp_ctx, b,
10264                                                         printer);
10265         }
10266
10267 done:
10268         talloc_free(tmp_ctx);
10269         return status;
10270 }
10271
10272 /****************************************************************
10273  _spoolss_EnumPrinterDataEx
10274 ****************************************************************/
10275
10276 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10277                                   struct spoolss_EnumPrinterDataEx *r)
10278 {
10279         uint32_t        count = 0;
10280         struct spoolss_PrinterEnumValues *info = NULL;
10281         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10282         int             snum;
10283         WERROR          result;
10284
10285         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10286
10287         *r->out.count = 0;
10288         *r->out.needed = 0;
10289         *r->out.info = NULL;
10290
10291         if (!Printer) {
10292                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10293                         OUR_HANDLE(r->in.handle)));
10294                 return WERR_INVALID_HANDLE;
10295         }
10296
10297         /*
10298          * first check for a keyname of NULL or "".  Win2k seems to send
10299          * this a lot and we should send back WERR_INVALID_PARAMETER
10300          * no need to spend time looking up the printer in this case.
10301          * --jerry
10302          */
10303
10304         if (!strlen(r->in.key_name)) {
10305                 result = WERR_INVALID_PARAMETER;
10306                 goto done;
10307         }
10308
10309         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10310                 return WERR_INVALID_HANDLE;
10311         }
10312
10313         /* now look for a match on the key name */
10314         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10315                                             get_session_info_system(),
10316                                             p->msg_ctx,
10317                                             lp_const_servicename(snum),
10318                                             r->in.key_name,
10319                                             &count,
10320                                             &info);
10321         if (!W_ERROR_IS_OK(result)) {
10322                 goto done;
10323         }
10324
10325 #if 0 /* FIXME - gd */
10326         /* housekeeping information in the reply */
10327
10328         /* Fix from Martin Zielinski <mz@seh.de> - ensure
10329          * the hand marshalled container size is a multiple
10330          * of 4 bytes for RPC alignment.
10331          */
10332
10333         if (needed % 4) {
10334                 needed += 4-(needed % 4);
10335         }
10336 #endif
10337         *r->out.count   = count;
10338         *r->out.info    = info;
10339
10340  done:
10341         if (!W_ERROR_IS_OK(result)) {
10342                 return result;
10343         }
10344
10345         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10346                                                spoolss_EnumPrinterDataEx,
10347                                                *r->out.info,
10348                                                *r->out.count);
10349         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10350         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10351
10352         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10353 }
10354
10355 /****************************************************************************
10356 ****************************************************************************/
10357
10358 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10359                                                  const char *servername,
10360                                                  const char *environment,
10361                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
10362 {
10363         WERROR werr;
10364         char *path = NULL;
10365
10366         werr = compose_spoolss_server_path(mem_ctx,
10367                                            servername,
10368                                            environment,
10369                                            SPOOLSS_PRTPROCS_PATH,
10370                                            &path);
10371         if (!W_ERROR_IS_OK(werr)) {
10372                 return werr;
10373         }
10374
10375         DEBUG(4,("print processor directory: [%s]\n", path));
10376
10377         r->directory_name = path;
10378
10379         return WERR_OK;
10380 }
10381
10382 /****************************************************************
10383  _spoolss_GetPrintProcessorDirectory
10384 ****************************************************************/
10385
10386 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10387                                            struct spoolss_GetPrintProcessorDirectory *r)
10388 {
10389         WERROR result;
10390         char *prnproc_share = NULL;
10391         bool prnproc_share_exists = false;
10392         int snum;
10393
10394         /* that's an [in out] buffer */
10395
10396         if (!r->in.buffer && (r->in.offered != 0)) {
10397                 result = WERR_INVALID_PARAMETER;
10398                 goto err_info_free;
10399         }
10400
10401         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10402                 r->in.level));
10403
10404         *r->out.needed = 0;
10405
10406         /* r->in.level is ignored */
10407
10408         /* We always should reply with a local print processor directory so that
10409          * users are not forced to have a [prnproc$] share on the Samba spoolss
10410          * server, if users decide to do so, lets announce it though - Guenther */
10411
10412         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10413         if (!prnproc_share) {
10414                 result = WERR_NOT_ENOUGH_MEMORY;
10415                 goto err_info_free;
10416         }
10417         if (snum != -1) {
10418                 prnproc_share_exists = true;
10419         }
10420
10421         result = getprintprocessordirectory_level_1(p->mem_ctx,
10422                                                     prnproc_share_exists ? r->in.server : NULL,
10423                                                     r->in.environment,
10424                                                     &r->out.info->info1);
10425         if (!W_ERROR_IS_OK(result)) {
10426                 goto err_info_free;
10427         }
10428
10429         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10430                                                                                    r->out.info, r->in.level);
10431         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10432
10433         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10434
10435 err_info_free:
10436         TALLOC_FREE(r->out.info);
10437         return result;
10438 }
10439
10440 /*******************************************************************
10441  ********************************************************************/
10442
10443 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10444                                const char *dllname)
10445 {
10446         enum ndr_err_code ndr_err;
10447         struct spoolss_MonitorUi ui;
10448
10449         ui.dll_name = dllname;
10450
10451         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10452                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10453         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10454                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10455         }
10456         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10457 }
10458
10459 /*******************************************************************
10460  Streams the monitor UI DLL name in UNICODE
10461 *******************************************************************/
10462
10463 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10464                                struct security_token *token, DATA_BLOB *in,
10465                                DATA_BLOB *out, uint32_t *needed)
10466 {
10467         const char *dllname = "tcpmonui.dll";
10468
10469         *needed = (strlen(dllname)+1) * 2;
10470
10471         if (out->length < *needed) {
10472                 return WERR_INSUFFICIENT_BUFFER;
10473         }
10474
10475         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10476                 return WERR_NOT_ENOUGH_MEMORY;
10477         }
10478
10479         return WERR_OK;
10480 }
10481
10482 /*******************************************************************
10483  ********************************************************************/
10484
10485 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10486                              struct spoolss_PortData1 *port1,
10487                              const DATA_BLOB *buf)
10488 {
10489         enum ndr_err_code ndr_err;
10490         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10491                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10492         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10493                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10494         }
10495         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10496 }
10497
10498 /*******************************************************************
10499  ********************************************************************/
10500
10501 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10502                              struct spoolss_PortData2 *port2,
10503                              const DATA_BLOB *buf)
10504 {
10505         enum ndr_err_code ndr_err;
10506         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10507                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10508         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10509                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10510         }
10511         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10512 }
10513
10514 /*******************************************************************
10515  Create a new TCP/IP port
10516 *******************************************************************/
10517
10518 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10519                              struct security_token *token, DATA_BLOB *in,
10520                              DATA_BLOB *out, uint32_t *needed)
10521 {
10522         struct spoolss_PortData1 port1;
10523         struct spoolss_PortData2 port2;
10524         char *device_uri = NULL;
10525         uint32_t version;
10526
10527         const char *portname;
10528         const char *hostaddress;
10529         const char *queue;
10530         uint32_t port_number;
10531         uint32_t protocol;
10532
10533         /* peek for spoolss_PortData version */
10534
10535         if (!in || (in->length < (128 + 4))) {
10536                 return WERR_GEN_FAILURE;
10537         }
10538
10539         version = IVAL(in->data, 128);
10540
10541         switch (version) {
10542                 case 1:
10543                         ZERO_STRUCT(port1);
10544
10545                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10546                                 return WERR_NOT_ENOUGH_MEMORY;
10547                         }
10548
10549                         portname        = port1.portname;
10550                         hostaddress     = port1.hostaddress;
10551                         queue           = port1.queue;
10552                         protocol        = port1.protocol;
10553                         port_number     = port1.port_number;
10554
10555                         break;
10556                 case 2:
10557                         ZERO_STRUCT(port2);
10558
10559                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10560                                 return WERR_NOT_ENOUGH_MEMORY;
10561                         }
10562
10563                         portname        = port2.portname;
10564                         hostaddress     = port2.hostaddress;
10565                         queue           = port2.queue;
10566                         protocol        = port2.protocol;
10567                         port_number     = port2.port_number;
10568
10569                         break;
10570                 default:
10571                         DEBUG(1,("xcvtcp_addport: "
10572                                 "unknown version of port_data: %d\n", version));
10573                         return WERR_UNKNOWN_PORT;
10574         }
10575
10576         /* create the device URI and call the add_port_hook() */
10577
10578         switch (protocol) {
10579         case PROTOCOL_RAWTCP_TYPE:
10580                 device_uri = talloc_asprintf(mem_ctx,
10581                                 "socket://%s:%d/", hostaddress,
10582                                 port_number);
10583                 break;
10584
10585         case PROTOCOL_LPR_TYPE:
10586                 device_uri = talloc_asprintf(mem_ctx,
10587                         "lpr://%s/%s", hostaddress, queue );
10588                 break;
10589
10590         default:
10591                 return WERR_UNKNOWN_PORT;
10592         }
10593
10594         if (!device_uri) {
10595                 return WERR_NOT_ENOUGH_MEMORY;
10596         }
10597
10598         return add_port_hook(mem_ctx, token, portname, device_uri);
10599 }
10600
10601 /*******************************************************************
10602 *******************************************************************/
10603
10604 struct xcv_api_table xcvtcp_cmds[] = {
10605         { "MonitorUI",  xcvtcp_monitorui },
10606         { "AddPort",    xcvtcp_addport},
10607         { NULL,         NULL }
10608 };
10609
10610 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10611                                      struct security_token *token, const char *command,
10612                                      DATA_BLOB *inbuf,
10613                                      DATA_BLOB *outbuf,
10614                                      uint32_t *needed )
10615 {
10616         int i;
10617
10618         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10619
10620         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10621                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10622                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10623         }
10624
10625         return WERR_INVALID_FUNCTION;
10626 }
10627
10628 /*******************************************************************
10629 *******************************************************************/
10630 #if 0   /* don't support management using the "Local Port" monitor */
10631
10632 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10633                                  struct security_token *token, DATA_BLOB *in,
10634                                  DATA_BLOB *out, uint32_t *needed)
10635 {
10636         const char *dllname = "localui.dll";
10637
10638         *needed = (strlen(dllname)+1) * 2;
10639
10640         if (out->length < *needed) {
10641                 return WERR_INSUFFICIENT_BUFFER;
10642         }
10643
10644         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10645                 return WERR_NOT_ENOUGH_MEMORY;
10646         }
10647
10648         return WERR_OK;
10649 }
10650
10651 /*******************************************************************
10652 *******************************************************************/
10653
10654 struct xcv_api_table xcvlocal_cmds[] = {
10655         { "MonitorUI",  xcvlocal_monitorui },
10656         { NULL,         NULL }
10657 };
10658 #else
10659 struct xcv_api_table xcvlocal_cmds[] = {
10660         { NULL,         NULL }
10661 };
10662 #endif
10663
10664
10665
10666 /*******************************************************************
10667 *******************************************************************/
10668
10669 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10670                                        struct security_token *token, const char *command,
10671                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10672                                        uint32_t *needed)
10673 {
10674         int i;
10675
10676         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10677
10678         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10679                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10680                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10681         }
10682         return WERR_INVALID_FUNCTION;
10683 }
10684
10685 /****************************************************************
10686  _spoolss_XcvData
10687 ****************************************************************/
10688
10689 WERROR _spoolss_XcvData(struct pipes_struct *p,
10690                         struct spoolss_XcvData *r)
10691 {
10692         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10693         DATA_BLOB out_data = data_blob_null;
10694         WERROR werror;
10695
10696         if (!Printer) {
10697                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10698                         OUR_HANDLE(r->in.handle)));
10699                 return WERR_INVALID_HANDLE;
10700         }
10701
10702         /* Has to be a handle to the TCP/IP port monitor */
10703
10704         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10705                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10706                 return WERR_INVALID_HANDLE;
10707         }
10708
10709         /* requires administrative access to the server */
10710
10711         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10712                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10713                 return WERR_ACCESS_DENIED;
10714         }
10715
10716         /* Allocate the outgoing buffer */
10717
10718         if (r->in.out_data_size) {
10719                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10720                 if (out_data.data == NULL) {
10721                         return WERR_NOT_ENOUGH_MEMORY;
10722                 }
10723         }
10724
10725         switch ( Printer->printer_type ) {
10726         case SPLHND_PORTMON_TCP:
10727                 werror = process_xcvtcp_command(p->mem_ctx,
10728                                                 p->session_info->security_token,
10729                                                 r->in.function_name,
10730                                                 &r->in.in_data, &out_data,
10731                                                 r->out.needed);
10732                 break;
10733         case SPLHND_PORTMON_LOCAL:
10734                 werror = process_xcvlocal_command(p->mem_ctx,
10735                                                   p->session_info->security_token,
10736                                                   r->in.function_name,
10737                                                   &r->in.in_data, &out_data,
10738                                                   r->out.needed);
10739                 break;
10740         default:
10741                 werror = WERR_INVALID_PRINT_MONITOR;
10742         }
10743
10744         if (!W_ERROR_IS_OK(werror)) {
10745                 return werror;
10746         }
10747
10748         *r->out.status_code = 0;
10749
10750         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10751                 memcpy(r->out.out_data, out_data.data,
10752                         MIN(r->in.out_data_size, out_data.length));
10753         }
10754
10755         return WERR_OK;
10756 }
10757
10758 /****************************************************************
10759  _spoolss_AddPrintProcessor
10760 ****************************************************************/
10761
10762 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10763                                   struct spoolss_AddPrintProcessor *r)
10764 {
10765         /* for now, just indicate success and ignore the add.  We'll
10766            automatically set the winprint processor for printer
10767            entries later.  Used to debug the LexMark Optra S 1855 PCL
10768            driver --jerry */
10769
10770         return WERR_OK;
10771 }
10772
10773 /****************************************************************
10774  _spoolss_AddPort
10775 ****************************************************************/
10776
10777 WERROR _spoolss_AddPort(struct pipes_struct *p,
10778                         struct spoolss_AddPort *r)
10779 {
10780         /* do what w2k3 does */
10781
10782         return WERR_NOT_SUPPORTED;
10783 }
10784
10785 /****************************************************************
10786  _spoolss_GetPrinterDriver
10787 ****************************************************************/
10788
10789 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10790                                  struct spoolss_GetPrinterDriver *r)
10791 {
10792         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10793         return WERR_NOT_SUPPORTED;
10794 }
10795
10796 /****************************************************************
10797  _spoolss_ReadPrinter
10798 ****************************************************************/
10799
10800 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10801                             struct spoolss_ReadPrinter *r)
10802 {
10803         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10804         return WERR_NOT_SUPPORTED;
10805 }
10806
10807 /****************************************************************
10808  _spoolss_WaitForPrinterChange
10809 ****************************************************************/
10810
10811 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10812                                      struct spoolss_WaitForPrinterChange *r)
10813 {
10814         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10815         return WERR_NOT_SUPPORTED;
10816 }
10817
10818 /****************************************************************
10819  _spoolss_ConfigurePort
10820 ****************************************************************/
10821
10822 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10823                               struct spoolss_ConfigurePort *r)
10824 {
10825         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10826         return WERR_NOT_SUPPORTED;
10827 }
10828
10829 /****************************************************************
10830  _spoolss_DeletePort
10831 ****************************************************************/
10832
10833 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10834                            struct spoolss_DeletePort *r)
10835 {
10836         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10837         return WERR_NOT_SUPPORTED;
10838 }
10839
10840 /****************************************************************
10841  _spoolss_CreatePrinterIC
10842 ****************************************************************/
10843
10844 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10845                                 struct spoolss_CreatePrinterIC *r)
10846 {
10847         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10848         return WERR_NOT_SUPPORTED;
10849 }
10850
10851 /****************************************************************
10852  _spoolss_PlayGDIScriptOnPrinterIC
10853 ****************************************************************/
10854
10855 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10856                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10857 {
10858         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10859         return WERR_NOT_SUPPORTED;
10860 }
10861
10862 /****************************************************************
10863  _spoolss_DeletePrinterIC
10864 ****************************************************************/
10865
10866 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10867                                 struct spoolss_DeletePrinterIC *r)
10868 {
10869         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10870         return WERR_NOT_SUPPORTED;
10871 }
10872
10873 /****************************************************************
10874  _spoolss_AddPrinterConnection
10875 ****************************************************************/
10876
10877 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10878                                      struct spoolss_AddPrinterConnection *r)
10879 {
10880         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10881         return WERR_NOT_SUPPORTED;
10882 }
10883
10884 /****************************************************************
10885  _spoolss_DeletePrinterConnection
10886 ****************************************************************/
10887
10888 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10889                                         struct spoolss_DeletePrinterConnection *r)
10890 {
10891         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10892         return WERR_NOT_SUPPORTED;
10893 }
10894
10895 /****************************************************************
10896  _spoolss_PrinterMessageBox
10897 ****************************************************************/
10898
10899 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10900                                   struct spoolss_PrinterMessageBox *r)
10901 {
10902         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10903         return WERR_NOT_SUPPORTED;
10904 }
10905
10906 /****************************************************************
10907  _spoolss_AddMonitor
10908 ****************************************************************/
10909
10910 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10911                            struct spoolss_AddMonitor *r)
10912 {
10913         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10914         return WERR_NOT_SUPPORTED;
10915 }
10916
10917 /****************************************************************
10918  _spoolss_DeleteMonitor
10919 ****************************************************************/
10920
10921 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10922                               struct spoolss_DeleteMonitor *r)
10923 {
10924         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10925         return WERR_NOT_SUPPORTED;
10926 }
10927
10928 /****************************************************************
10929  _spoolss_DeletePrintProcessor
10930 ****************************************************************/
10931
10932 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10933                                      struct spoolss_DeletePrintProcessor *r)
10934 {
10935         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10936         return WERR_NOT_SUPPORTED;
10937 }
10938
10939 /****************************************************************
10940  _spoolss_AddPrintProvidor
10941 ****************************************************************/
10942
10943 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10944                                  struct spoolss_AddPrintProvidor *r)
10945 {
10946         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10947         return WERR_NOT_SUPPORTED;
10948 }
10949
10950 /****************************************************************
10951  _spoolss_DeletePrintProvidor
10952 ****************************************************************/
10953
10954 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10955                                     struct spoolss_DeletePrintProvidor *r)
10956 {
10957         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10958         return WERR_NOT_SUPPORTED;
10959 }
10960
10961 /****************************************************************
10962  _spoolss_FindFirstPrinterChangeNotification
10963 ****************************************************************/
10964
10965 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10966                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10967 {
10968         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10969         return WERR_NOT_SUPPORTED;
10970 }
10971
10972 /****************************************************************
10973  _spoolss_FindNextPrinterChangeNotification
10974 ****************************************************************/
10975
10976 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10977                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10978 {
10979         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10980         return WERR_NOT_SUPPORTED;
10981 }
10982
10983 /****************************************************************
10984  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10985 ****************************************************************/
10986
10987 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10988                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10989 {
10990         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10991         return WERR_NOT_SUPPORTED;
10992 }
10993
10994 /****************************************************************
10995  _spoolss_ReplyOpenPrinter
10996 ****************************************************************/
10997
10998 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10999                                  struct spoolss_ReplyOpenPrinter *r)
11000 {
11001         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11002         return WERR_NOT_SUPPORTED;
11003 }
11004
11005 /****************************************************************
11006  _spoolss_RouterReplyPrinter
11007 ****************************************************************/
11008
11009 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
11010                                    struct spoolss_RouterReplyPrinter *r)
11011 {
11012         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11013         return WERR_NOT_SUPPORTED;
11014 }
11015
11016 /****************************************************************
11017  _spoolss_ReplyClosePrinter
11018 ****************************************************************/
11019
11020 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
11021                                   struct spoolss_ReplyClosePrinter *r)
11022 {
11023         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11024         return WERR_NOT_SUPPORTED;
11025 }
11026
11027 /****************************************************************
11028  _spoolss_AddPortEx
11029 ****************************************************************/
11030
11031 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
11032                           struct spoolss_AddPortEx *r)
11033 {
11034         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11035         return WERR_NOT_SUPPORTED;
11036 }
11037
11038 /****************************************************************
11039  _spoolss_RouterFindFirstPrinterChangeNotification
11040 ****************************************************************/
11041
11042 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
11043                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
11044 {
11045         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11046         return WERR_NOT_SUPPORTED;
11047 }
11048
11049 /****************************************************************
11050  _spoolss_SpoolerInit
11051 ****************************************************************/
11052
11053 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
11054                             struct spoolss_SpoolerInit *r)
11055 {
11056         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11057         return WERR_NOT_SUPPORTED;
11058 }
11059
11060 /****************************************************************
11061  _spoolss_ResetPrinterEx
11062 ****************************************************************/
11063
11064 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
11065                                struct spoolss_ResetPrinterEx *r)
11066 {
11067         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11068         return WERR_NOT_SUPPORTED;
11069 }
11070
11071 /****************************************************************
11072  _spoolss_RouterReplyPrinterEx
11073 ****************************************************************/
11074
11075 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
11076                                      struct spoolss_RouterReplyPrinterEx *r)
11077 {
11078         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11079         return WERR_NOT_SUPPORTED;
11080 }
11081
11082 /****************************************************************
11083  _spoolss_44
11084 ****************************************************************/
11085
11086 WERROR _spoolss_44(struct pipes_struct *p,
11087                    struct spoolss_44 *r)
11088 {
11089         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11090         return WERR_NOT_SUPPORTED;
11091 }
11092
11093 /****************************************************************
11094  _spoolss_SetPort
11095 ****************************************************************/
11096
11097 WERROR _spoolss_SetPort(struct pipes_struct *p,
11098                         struct spoolss_SetPort *r)
11099 {
11100         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11101         return WERR_NOT_SUPPORTED;
11102 }
11103
11104 /****************************************************************
11105  _spoolss_4a
11106 ****************************************************************/
11107
11108 WERROR _spoolss_4a(struct pipes_struct *p,
11109                    struct spoolss_4a *r)
11110 {
11111         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11112         return WERR_NOT_SUPPORTED;
11113 }
11114
11115 /****************************************************************
11116  _spoolss_4b
11117 ****************************************************************/
11118
11119 WERROR _spoolss_4b(struct pipes_struct *p,
11120                    struct spoolss_4b *r)
11121 {
11122         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11123         return WERR_NOT_SUPPORTED;
11124 }
11125
11126 /****************************************************************
11127  _spoolss_4c
11128 ****************************************************************/
11129
11130 WERROR _spoolss_4c(struct pipes_struct *p,
11131                    struct spoolss_4c *r)
11132 {
11133         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11134         return WERR_NOT_SUPPORTED;
11135 }
11136
11137 /****************************************************************
11138  _spoolss_53
11139 ****************************************************************/
11140
11141 WERROR _spoolss_53(struct pipes_struct *p,
11142                    struct spoolss_53 *r)
11143 {
11144         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11145         return WERR_NOT_SUPPORTED;
11146 }
11147
11148 /****************************************************************
11149  _spoolss_AddPerMachineConnection
11150 ****************************************************************/
11151
11152 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11153                                         struct spoolss_AddPerMachineConnection *r)
11154 {
11155         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11156         return WERR_NOT_SUPPORTED;
11157 }
11158
11159 /****************************************************************
11160  _spoolss_DeletePerMachineConnection
11161 ****************************************************************/
11162
11163 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11164                                            struct spoolss_DeletePerMachineConnection *r)
11165 {
11166         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11167         return WERR_NOT_SUPPORTED;
11168 }
11169
11170 /****************************************************************
11171  _spoolss_EnumPerMachineConnections
11172 ****************************************************************/
11173
11174 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11175                                           struct spoolss_EnumPerMachineConnections *r)
11176 {
11177         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11178         return WERR_NOT_SUPPORTED;
11179 }
11180
11181 /****************************************************************
11182  _spoolss_5a
11183 ****************************************************************/
11184
11185 WERROR _spoolss_5a(struct pipes_struct *p,
11186                    struct spoolss_5a *r)
11187 {
11188         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11189         return WERR_NOT_SUPPORTED;
11190 }
11191
11192 /****************************************************************
11193  _spoolss_5b
11194 ****************************************************************/
11195
11196 WERROR _spoolss_5b(struct pipes_struct *p,
11197                    struct spoolss_5b *r)
11198 {
11199         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11200         return WERR_NOT_SUPPORTED;
11201 }
11202
11203 /****************************************************************
11204  _spoolss_5c
11205 ****************************************************************/
11206
11207 WERROR _spoolss_5c(struct pipes_struct *p,
11208                    struct spoolss_5c *r)
11209 {
11210         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11211         return WERR_NOT_SUPPORTED;
11212 }
11213
11214 /****************************************************************
11215  _spoolss_5d
11216 ****************************************************************/
11217
11218 WERROR _spoolss_5d(struct pipes_struct *p,
11219                    struct spoolss_5d *r)
11220 {
11221         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11222         return WERR_NOT_SUPPORTED;
11223 }
11224
11225 /****************************************************************
11226  _spoolss_5e
11227 ****************************************************************/
11228
11229 WERROR _spoolss_5e(struct pipes_struct *p,
11230                    struct spoolss_5e *r)
11231 {
11232         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11233         return WERR_NOT_SUPPORTED;
11234 }
11235
11236 /****************************************************************
11237  _spoolss_5f
11238 ****************************************************************/
11239
11240 WERROR _spoolss_5f(struct pipes_struct *p,
11241                    struct spoolss_5f *r)
11242 {
11243         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11244         return WERR_NOT_SUPPORTED;
11245 }
11246
11247 /****************************************************************
11248  _spoolss_60
11249 ****************************************************************/
11250
11251 WERROR _spoolss_60(struct pipes_struct *p,
11252                    struct spoolss_60 *r)
11253 {
11254         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11255         return WERR_NOT_SUPPORTED;
11256 }
11257
11258 /****************************************************************
11259  _spoolss_SendRecvBidiData
11260 ****************************************************************/
11261
11262 WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11263                                  struct spoolss_SendRecvBidiData *r)
11264 {
11265         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11266         return WERR_NOT_SUPPORTED;
11267 }
11268
11269 /****************************************************************
11270  _spoolss_62
11271 ****************************************************************/
11272
11273 WERROR _spoolss_62(struct pipes_struct *p,
11274                    struct spoolss_62 *r)
11275 {
11276         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11277         return WERR_NOT_SUPPORTED;
11278 }
11279
11280 /****************************************************************
11281  _spoolss_63
11282 ****************************************************************/
11283
11284 WERROR _spoolss_63(struct pipes_struct *p,
11285                    struct spoolss_63 *r)
11286 {
11287         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11288         return WERR_NOT_SUPPORTED;
11289 }
11290
11291 /****************************************************************
11292  _spoolss_64
11293 ****************************************************************/
11294
11295 WERROR _spoolss_64(struct pipes_struct *p,
11296                    struct spoolss_64 *r)
11297 {
11298         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11299         return WERR_NOT_SUPPORTED;
11300 }
11301
11302 /****************************************************************
11303  _spoolss_65
11304 ****************************************************************/
11305
11306 WERROR _spoolss_65(struct pipes_struct *p,
11307                    struct spoolss_65 *r)
11308 {
11309         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11310         return WERR_NOT_SUPPORTED;
11311 }
11312
11313 /****************************************************************
11314  _spoolss_GetCorePrinterDrivers
11315 ****************************************************************/
11316
11317 HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11318                                        struct spoolss_GetCorePrinterDrivers *r)
11319 {
11320         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11321         return HRES_ERROR_NOT_SUPPORTED;
11322 }
11323
11324 /****************************************************************
11325  _spoolss_67
11326 ****************************************************************/
11327
11328 WERROR _spoolss_67(struct pipes_struct *p,
11329                    struct spoolss_67 *r)
11330 {
11331         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11332         return WERR_NOT_SUPPORTED;
11333 }
11334
11335 /****************************************************************
11336  _spoolss_GetPrinterDriverPackagePath
11337 ****************************************************************/
11338
11339 HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11340                                              struct spoolss_GetPrinterDriverPackagePath *r)
11341 {
11342         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11343         return HRES_ERROR_NOT_SUPPORTED;
11344 }
11345
11346 /****************************************************************
11347  _spoolss_69
11348 ****************************************************************/
11349
11350 WERROR _spoolss_69(struct pipes_struct *p,
11351                    struct spoolss_69 *r)
11352 {
11353         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11354         return WERR_NOT_SUPPORTED;
11355 }
11356
11357 /****************************************************************
11358  _spoolss_6a
11359 ****************************************************************/
11360
11361 WERROR _spoolss_6a(struct pipes_struct *p,
11362                    struct spoolss_6a *r)
11363 {
11364         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11365         return WERR_NOT_SUPPORTED;
11366 }
11367
11368 /****************************************************************
11369  _spoolss_6b
11370 ****************************************************************/
11371
11372 WERROR _spoolss_6b(struct pipes_struct *p,
11373                    struct spoolss_6b *r)
11374 {
11375         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11376         return WERR_NOT_SUPPORTED;
11377 }
11378
11379 /****************************************************************
11380  _spoolss_6c
11381 ****************************************************************/
11382
11383 WERROR _spoolss_6c(struct pipes_struct *p,
11384                    struct spoolss_6c *r)
11385 {
11386         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11387         return WERR_NOT_SUPPORTED;
11388 }
11389
11390 /****************************************************************
11391  _spoolss_6d
11392 ****************************************************************/
11393
11394 WERROR _spoolss_6d(struct pipes_struct *p,
11395                    struct spoolss_6d *r)
11396 {
11397         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11398         return WERR_NOT_SUPPORTED;
11399 }
11400
11401 /****************************************************************
11402  _spoolss_GetJobNamedPropertyValue
11403 ****************************************************************/
11404
11405 WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11406                                          struct spoolss_GetJobNamedPropertyValue *r)
11407 {
11408         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11409         return WERR_NOT_SUPPORTED;
11410 }
11411
11412 /****************************************************************
11413  _spoolss_SetJobNamedProperty
11414 ****************************************************************/
11415
11416 WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11417                                     struct spoolss_SetJobNamedProperty *r)
11418 {
11419         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11420         return WERR_NOT_SUPPORTED;
11421 }
11422
11423 /****************************************************************
11424  _spoolss_DeleteJobNamedProperty
11425 ****************************************************************/
11426
11427 WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11428                                        struct spoolss_DeleteJobNamedProperty *r)
11429 {
11430         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11431         return WERR_NOT_SUPPORTED;
11432 }
11433
11434 /****************************************************************
11435  _spoolss_EnumJobNamedProperties
11436 ****************************************************************/
11437
11438 WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11439                                        struct spoolss_EnumJobNamedProperties *r)
11440 {
11441         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11442         return WERR_NOT_SUPPORTED;
11443 }
11444
11445 /****************************************************************
11446  _spoolss_72
11447 ****************************************************************/
11448
11449 WERROR _spoolss_72(struct pipes_struct *p,
11450                    struct spoolss_72 *r)
11451 {
11452         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11453         return WERR_NOT_SUPPORTED;
11454 }
11455
11456 /****************************************************************
11457  _spoolss_73
11458 ****************************************************************/
11459
11460 WERROR _spoolss_73(struct pipes_struct *p,
11461                    struct spoolss_73 *r)
11462 {
11463         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11464         return WERR_NOT_SUPPORTED;
11465 }
11466
11467 /****************************************************************
11468  _spoolss_RpcLogJobInfoForBranchOffice
11469 ****************************************************************/
11470
11471 WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11472                                           struct spoolss_LogJobInfoForBranchOffice *r)
11473 {
11474         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11475         return WERR_NOT_SUPPORTED;
11476 }