306b8b294d52876d78260ec7c19dd1706b788137
[metze/samba/wip.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
59
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62         ((info)?ndr_size_##fn(info, level, 0):0)
63
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
66
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
69
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71
72 #undef DBGC_CLASS
73 #define DBGC_CLASS DBGC_RPC_SRV
74
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
77 #endif
78
79 struct notify_back_channel;
80
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86         struct printer_handle *prev, *next;
87         bool document_started;
88         bool page_started;
89         uint32 jobid; /* jobid in printing backend */
90         int printer_type;
91         const char *servername;
92         fstring sharename;
93         uint32 type;
94         uint32 access_granted;
95         struct {
96                 uint32 flags;
97                 uint32 options;
98                 fstring localmachine;
99                 uint32 printerlocal;
100                 struct spoolss_NotifyOption *option;
101                 struct policy_handle cli_hnd;
102                 struct notify_back_channel *cli_chan;
103                 uint32 change;
104                 /* are we in a FindNextPrinterChangeNotify() call? */
105                 bool fnpcn;
106                 struct messaging_context *msg_ctx;
107         } notify;
108         struct {
109                 fstring machine;
110                 fstring user;
111         } client;
112
113         /* devmode sent in the OpenPrinter() call */
114         struct spoolss_DeviceMode *devmode;
115
116         /* TODO cache the printer info2 structure */
117         struct spoolss_PrinterInfo2 *info2;
118
119 };
120
121 static struct printer_handle *printers_list;
122
123 struct printer_session_counter {
124         struct printer_session_counter *next;
125         struct printer_session_counter *prev;
126
127         int snum;
128         uint32_t counter;
129 };
130
131 static struct printer_session_counter *counter_list;
132
133 struct notify_back_channel {
134         struct notify_back_channel *prev, *next;
135
136         /* associated client */
137         struct sockaddr_storage client_address;
138
139         /* print notify back-channel pipe handle*/
140         struct rpc_pipe_client *cli_pipe;
141         uint32_t active_connections;
142 };
143
144 static struct notify_back_channel *back_channels;
145
146 /* Map generic permissions to printer object specific permissions */
147
148 const struct standard_mapping printer_std_mapping = {
149         PRINTER_READ,
150         PRINTER_WRITE,
151         PRINTER_EXECUTE,
152         PRINTER_ALL_ACCESS
153 };
154
155 /* Map generic permissions to print server object specific permissions */
156
157 const struct standard_mapping printserver_std_mapping = {
158         SERVER_READ,
159         SERVER_WRITE,
160         SERVER_EXECUTE,
161         SERVER_ALL_ACCESS
162 };
163
164 /* API table for Xcv Monitor functions */
165
166 struct xcv_api_table {
167         const char *name;
168         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
169 };
170
171 static void prune_printername_cache(void);
172
173 /********************************************************************
174  * Canonicalize servername.
175  ********************************************************************/
176
177 static const char *canon_servername(const char *servername)
178 {
179         const char *pservername = servername;
180         while (*pservername == '\\') {
181                 pservername++;
182         }
183         return pservername;
184 }
185
186 /* translate between internal status numbers and NT status numbers */
187 static int nt_printj_status(int v)
188 {
189         switch (v) {
190         case LPQ_QUEUED:
191                 return 0;
192         case LPQ_PAUSED:
193                 return JOB_STATUS_PAUSED;
194         case LPQ_SPOOLING:
195                 return JOB_STATUS_SPOOLING;
196         case LPQ_PRINTING:
197                 return JOB_STATUS_PRINTING;
198         case LPQ_ERROR:
199                 return JOB_STATUS_ERROR;
200         case LPQ_DELETING:
201                 return JOB_STATUS_DELETING;
202         case LPQ_OFFLINE:
203                 return JOB_STATUS_OFFLINE;
204         case LPQ_PAPEROUT:
205                 return JOB_STATUS_PAPEROUT;
206         case LPQ_PRINTED:
207                 return JOB_STATUS_PRINTED;
208         case LPQ_DELETED:
209                 return JOB_STATUS_DELETED;
210         case LPQ_BLOCKED:
211                 return JOB_STATUS_BLOCKED_DEVQ;
212         case LPQ_USER_INTERVENTION:
213                 return JOB_STATUS_USER_INTERVENTION;
214         }
215         return 0;
216 }
217
218 static int nt_printq_status(int v)
219 {
220         switch (v) {
221         case LPQ_PAUSED:
222                 return PRINTER_STATUS_PAUSED;
223         case LPQ_QUEUED:
224         case LPQ_SPOOLING:
225         case LPQ_PRINTING:
226                 return 0;
227         }
228         return 0;
229 }
230
231 /***************************************************************************
232  Disconnect from the client
233 ****************************************************************************/
234
235 static void srv_spoolss_replycloseprinter(int snum,
236                                           struct printer_handle *prn_hnd)
237 {
238         WERROR result;
239         NTSTATUS status;
240
241         /*
242          * Tell the specific printing tdb we no longer want messages for this printer
243          * by deregistering our PID.
244          */
245
246         if (!print_notify_deregister_pid(snum)) {
247                 DEBUG(0, ("Failed to register our pid for printer %s\n",
248                           lp_const_servicename(snum)));
249         }
250
251         /* weird if the test succeeds !!! */
252         if (prn_hnd->notify.cli_chan == NULL ||
253             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
254             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
255             prn_hnd->notify.cli_chan->active_connections == 0) {
256                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
257                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
258                 TALLOC_FREE(prn_hnd->notify.cli_chan);
259                 return;
260         }
261
262         status = dcerpc_spoolss_ReplyClosePrinter(
263                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
264                                         talloc_tos(),
265                                         &prn_hnd->notify.cli_hnd,
266                                         &result);
267         if (!NT_STATUS_IS_OK(status)) {
268                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
269                           nt_errstr(status)));
270                 result = ntstatus_to_werror(status);
271         } else if (!W_ERROR_IS_OK(result)) {
272                 DEBUG(0, ("reply_close_printer failed [%s].\n",
273                           win_errstr(result)));
274         }
275
276         /* if it's the last connection, deconnect the IPC$ share */
277         if (prn_hnd->notify.cli_chan->active_connections == 1) {
278
279                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
280                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
281                 TALLOC_FREE(prn_hnd->notify.cli_chan);
282
283                 if (prn_hnd->notify.msg_ctx != NULL) {
284                         messaging_deregister(prn_hnd->notify.msg_ctx,
285                                              MSG_PRINTER_NOTIFY2, NULL);
286                 }
287         }
288
289         if (prn_hnd->notify.cli_chan) {
290                 prn_hnd->notify.cli_chan->active_connections--;
291                 prn_hnd->notify.cli_chan = NULL;
292         }
293 }
294
295 /****************************************************************************
296  Functions to free a printer entry datastruct.
297 ****************************************************************************/
298
299 static int printer_entry_destructor(struct printer_handle *Printer)
300 {
301         if (Printer->notify.cli_chan != NULL &&
302             Printer->notify.cli_chan->active_connections > 0) {
303                 int snum = -1;
304
305                 switch(Printer->printer_type) {
306                 case SPLHND_SERVER:
307                         srv_spoolss_replycloseprinter(snum, Printer);
308                         break;
309
310                 case SPLHND_PRINTER:
311                         snum = print_queue_snum(Printer->sharename);
312                         if (snum != -1) {
313                                 srv_spoolss_replycloseprinter(snum, Printer);
314                         }
315                         break;
316                 default:
317                         break;
318                 }
319         }
320
321         Printer->notify.flags=0;
322         Printer->notify.options=0;
323         Printer->notify.localmachine[0]='\0';
324         Printer->notify.printerlocal=0;
325         TALLOC_FREE(Printer->notify.option);
326         TALLOC_FREE(Printer->devmode);
327
328         /* Remove from the internal list. */
329         DLIST_REMOVE(printers_list, Printer);
330         return 0;
331 }
332
333 /****************************************************************************
334   find printer index by handle
335 ****************************************************************************/
336
337 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
338                                                         struct policy_handle *hnd)
339 {
340         struct printer_handle *find_printer = NULL;
341
342         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
343                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
344                 return NULL;
345         }
346
347         return find_printer;
348 }
349
350 /****************************************************************************
351  Close printer index by handle.
352 ****************************************************************************/
353
354 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
355 {
356         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
357
358         if (!Printer) {
359                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
360                         OUR_HANDLE(hnd)));
361                 return false;
362         }
363
364         close_policy_hnd(p, hnd);
365
366         return true;
367 }
368
369 /****************************************************************************
370  Delete a printer given a handle.
371 ****************************************************************************/
372
373 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
374                                   const char *sharename,
375                                   struct messaging_context *msg_ctx)
376 {
377         char *cmd = lp_deleteprinter_cmd(talloc_tos());
378         char *command = NULL;
379         int ret;
380         bool is_print_op = false;
381
382         /* can't fail if we don't try */
383
384         if ( !*cmd )
385                 return WERR_OK;
386
387         command = talloc_asprintf(ctx,
388                         "%s \"%s\"",
389                         cmd, sharename);
390         if (!command) {
391                 return WERR_NOMEM;
392         }
393         if ( token )
394                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
395
396         DEBUG(10,("Running [%s]\n", command));
397
398         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
399
400         if ( is_print_op )
401                 become_root();
402
403         if ( (ret = smbrun(command, NULL)) == 0 ) {
404                 /* Tell everyone we updated smb.conf. */
405                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
406         }
407
408         if ( is_print_op )
409                 unbecome_root();
410
411         /********** END SePrintOperatorPrivlege BLOCK **********/
412
413         DEBUGADD(10,("returned [%d]\n", ret));
414
415         TALLOC_FREE(command);
416
417         if (ret != 0)
418                 return WERR_BADFID; /* What to return here? */
419
420         return WERR_OK;
421 }
422
423 /****************************************************************************
424  Delete a printer given a handle.
425 ****************************************************************************/
426
427 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
428 {
429         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
430         WERROR result;
431
432         if (!Printer) {
433                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
434                         OUR_HANDLE(hnd)));
435                 return WERR_BADFID;
436         }
437
438         /*
439          * It turns out that Windows allows delete printer on a handle
440          * opened by an admin user, then used on a pipe handle created
441          * by an anonymous user..... but they're working on security.... riiight !
442          * JRA.
443          */
444
445         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
446                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
447                 return WERR_ACCESS_DENIED;
448         }
449
450         /* this does not need a become root since the access check has been
451            done on the handle already */
452
453         result = winreg_delete_printer_key_internal(p->mem_ctx,
454                                            get_session_info_system(),
455                                            p->msg_ctx,
456                                            Printer->sharename,
457                                            "");
458         if (!W_ERROR_IS_OK(result)) {
459                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
460                 return WERR_BADFID;
461         }
462
463         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
464                                      Printer->sharename, p->msg_ctx);
465         if (!W_ERROR_IS_OK(result)) {
466                 return result;
467         }
468         prune_printername_cache();
469         return WERR_OK;
470 }
471
472 /****************************************************************************
473  Return the snum of a printer corresponding to an handle.
474 ****************************************************************************/
475
476 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
477                              int *number, struct share_params **params)
478 {
479         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
480
481         if (!Printer) {
482                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
483                         OUR_HANDLE(hnd)));
484                 return false;
485         }
486
487         switch (Printer->printer_type) {
488                 case SPLHND_PRINTER:
489                         DEBUG(4,("short name:%s\n", Printer->sharename));
490                         *number = print_queue_snum(Printer->sharename);
491                         return (*number != -1);
492                 case SPLHND_SERVER:
493                         return false;
494                 default:
495                         return false;
496         }
497 }
498
499 /****************************************************************************
500  Set printer handle type.
501  Check if it's \\server or \\server\printer
502 ****************************************************************************/
503
504 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
505 {
506         DEBUG(3,("Setting printer type=%s\n", handlename));
507
508         /* it's a print server */
509         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
510                 DEBUGADD(4,("Printer is a print server\n"));
511                 Printer->printer_type = SPLHND_SERVER;
512         }
513         /* it's a printer (set_printer_hnd_name() will handle port monitors */
514         else {
515                 DEBUGADD(4,("Printer is a printer\n"));
516                 Printer->printer_type = SPLHND_PRINTER;
517         }
518
519         return true;
520 }
521
522 static void prune_printername_cache_fn(const char *key, const char *value,
523                                        time_t timeout, void *private_data)
524 {
525         gencache_del(key);
526 }
527
528 static void prune_printername_cache(void)
529 {
530         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
531 }
532
533 /****************************************************************************
534  Set printer handle name..  Accept names like \\server, \\server\printer,
535  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
536  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
537  XcvDataPort() interface.
538 ****************************************************************************/
539
540 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
541                                    const struct auth_session_info *session_info,
542                                    struct messaging_context *msg_ctx,
543                                    struct printer_handle *Printer,
544                                    const char *handlename)
545 {
546         int snum;
547         int n_services=lp_numservices();
548         char *aprinter;
549         const char *printername;
550         const char *servername = NULL;
551         fstring sname;
552         bool found = false;
553         struct spoolss_PrinterInfo2 *info2 = NULL;
554         WERROR result;
555         char *p;
556
557         /*
558          * Hopefully nobody names his printers like this. Maybe \ or ,
559          * are illegal in printer names even?
560          */
561         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
562         char *cache_key;
563         char *tmp;
564
565         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
566                 (unsigned long)strlen(handlename)));
567
568         aprinter = discard_const_p(char, handlename);
569         if ( *handlename == '\\' ) {
570                 servername = canon_servername(handlename);
571                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
572                         *aprinter = '\0';
573                         aprinter++;
574                 }
575                 if (!is_myname_or_ipaddr(servername)) {
576                         return WERR_INVALID_PRINTER_NAME;
577                 }
578                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
579                 if (Printer->servername == NULL) {
580                         return WERR_NOMEM;
581                 }
582         }
583
584         if (Printer->printer_type == SPLHND_SERVER) {
585                 return WERR_OK;
586         }
587
588         if (Printer->printer_type != SPLHND_PRINTER) {
589                 return WERR_INVALID_HANDLE;
590         }
591
592         DEBUGADD(5, ("searching for [%s]\n", aprinter));
593
594         p = strchr(aprinter, ',');
595         if (p != NULL) {
596                 char *p2 = p;
597                 p++;
598                 if (*p == ' ') {
599                         p++;
600                 }
601                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
602                         *p2 = '\0';
603                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
604                         *p2 = '\0';
605                 }
606         }
607
608         if (p) {
609                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
610         }
611
612         /* check for the Port Monitor Interface */
613         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
614                 Printer->printer_type = SPLHND_PORTMON_TCP;
615                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
616                 found = true;
617         }
618         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
619                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
620                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
621                 found = true;
622         }
623
624         /*
625          * With hundreds of printers, the "for" loop iterating all
626          * shares can be quite expensive, as it is done on every
627          * OpenPrinter. The loop maps "aprinter" to "sname", the
628          * result of which we cache in gencache.
629          */
630
631         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
632                                     aprinter);
633         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
634
635                 found = (strcmp(tmp, printer_not_found) != 0);
636                 if (!found) {
637                         DEBUG(4, ("Printer %s not found\n", aprinter));
638                         SAFE_FREE(tmp);
639                         return WERR_INVALID_PRINTER_NAME;
640                 }
641                 fstrcpy(sname, tmp);
642                 SAFE_FREE(tmp);
643         }
644
645         /* Search all sharenames first as this is easier than pulling
646            the printer_info_2 off of disk. Don't use find_service() since
647            that calls out to map_username() */
648
649         /* do another loop to look for printernames */
650         for (snum = 0; !found && snum < n_services; snum++) {
651                 const char *printer = lp_const_servicename(snum);
652
653                 /* no point going on if this is not a printer */
654                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
655                         continue;
656                 }
657
658                 /* ignore [printers] share */
659                 if (strequal(printer, "printers")) {
660                         continue;
661                 }
662
663                 fstrcpy(sname, printer);
664                 if (strequal(aprinter, printer)) {
665                         found = true;
666                         break;
667                 }
668
669                 /* no point looking up the printer object if
670                    we aren't allowing printername != sharename */
671                 if (lp_force_printername(snum)) {
672                         continue;
673                 }
674
675                 result = winreg_get_printer_internal(mem_ctx,
676                                             session_info,
677                                             msg_ctx,
678                                             sname,
679                                             &info2);
680                 if ( !W_ERROR_IS_OK(result) ) {
681                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
682                                  sname, win_errstr(result)));
683                         continue;
684                 }
685
686                 printername = strrchr(info2->printername, '\\');
687                 if (printername == NULL) {
688                         printername = info2->printername;
689                 } else {
690                         printername++;
691                 }
692
693                 if (strequal(printername, aprinter)) {
694                         found = true;
695                         break;
696                 }
697
698                 DEBUGADD(10, ("printername: %s\n", printername));
699
700                 TALLOC_FREE(info2);
701         }
702
703         if ( !found ) {
704                 if (cache_key != NULL) {
705                         gencache_set(cache_key, printer_not_found,
706                                      time(NULL)+300);
707                         TALLOC_FREE(cache_key);
708                 }
709                 DEBUGADD(4,("Printer not found\n"));
710                 return WERR_INVALID_PRINTER_NAME;
711         }
712
713         if (cache_key != NULL) {
714                 gencache_set(cache_key, sname, time(NULL)+300);
715                 TALLOC_FREE(cache_key);
716         }
717
718         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
719
720         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
721
722         return WERR_OK;
723 }
724
725 /****************************************************************************
726  Find first available printer slot. creates a printer handle for you.
727  ****************************************************************************/
728
729 static WERROR open_printer_hnd(struct pipes_struct *p,
730                                struct policy_handle *hnd,
731                                const char *name,
732                                uint32_t access_granted)
733 {
734         struct printer_handle *new_printer;
735         WERROR result;
736
737         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
738
739         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
740         if (new_printer == NULL) {
741                 return WERR_NOMEM;
742         }
743         talloc_set_destructor(new_printer, printer_entry_destructor);
744
745         /* This also steals the printer_handle on the policy_handle */
746         if (!create_policy_hnd(p, hnd, new_printer)) {
747                 TALLOC_FREE(new_printer);
748                 return WERR_INVALID_HANDLE;
749         }
750
751         /* Add to the internal list. */
752         DLIST_ADD(printers_list, new_printer);
753
754         new_printer->notify.option=NULL;
755
756         if (!set_printer_hnd_printertype(new_printer, name)) {
757                 close_printer_handle(p, hnd);
758                 return WERR_INVALID_HANDLE;
759         }
760
761         result = set_printer_hnd_name(p->mem_ctx,
762                                       get_session_info_system(),
763                                       p->msg_ctx,
764                                       new_printer, name);
765         if (!W_ERROR_IS_OK(result)) {
766                 close_printer_handle(p, hnd);
767                 return result;
768         }
769
770         new_printer->access_granted = access_granted;
771
772         DEBUG(5, ("%d printer handles active\n",
773                   (int)num_pipe_handles(p)));
774
775         return WERR_OK;
776 }
777
778 /***************************************************************************
779  check to see if the client motify handle is monitoring the notification
780  given by (notify_type, notify_field).
781  **************************************************************************/
782
783 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
784                                       uint16_t notify_field)
785 {
786         return true;
787 }
788
789 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
790                                 uint16_t notify_field)
791 {
792         struct spoolss_NotifyOption *option = p->notify.option;
793         uint32_t i, j;
794
795         /*
796          * Flags should always be zero when the change notify
797          * is registered by the client's spooler.  A user Win32 app
798          * might use the flags though instead of the NOTIFY_OPTION_INFO
799          * --jerry
800          */
801
802         if (!option) {
803                 return false;
804         }
805
806         if (p->notify.flags)
807                 return is_monitoring_event_flags(
808                         p->notify.flags, notify_type, notify_field);
809
810         for (i = 0; i < option->count; i++) {
811
812                 /* Check match for notify_type */
813
814                 if (option->types[i].type != notify_type)
815                         continue;
816
817                 /* Check match for field */
818
819                 for (j = 0; j < option->types[i].count; j++) {
820                         if (option->types[i].fields[j].field == notify_field) {
821                                 return true;
822                         }
823                 }
824         }
825
826         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
827                    p->servername, p->sharename, notify_type, notify_field));
828
829         return false;
830 }
831
832 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
833         _data->data.integer[0] = _integer; \
834         _data->data.integer[1] = 0;
835
836
837 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
838         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
839         if (!_data->data.string.string) {\
840                 _data->data.string.size = 0; \
841         } \
842         _data->data.string.size = strlen_m_term(_p) * 2;
843
844 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
845         _data->data.devmode.devmode = _devmode;
846
847 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
848         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
849         if (!_data->data.sd.sd) { \
850                 _data->data.sd.sd_size = 0; \
851         } \
852         _data->data.sd.sd_size = \
853                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
854
855 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
856                                    struct tm *t,
857                                    const char **pp,
858                                    uint32_t *plen)
859 {
860         struct spoolss_Time st;
861         uint32_t len = 16;
862         char *p;
863
864         if (!init_systemtime(&st, t)) {
865                 return;
866         }
867
868         p = talloc_array(mem_ctx, char, len);
869         if (!p) {
870                 return;
871         }
872
873         /*
874          * Systemtime must be linearized as a set of UINT16's.
875          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
876          */
877
878         SSVAL(p, 0, st.year);
879         SSVAL(p, 2, st.month);
880         SSVAL(p, 4, st.day_of_week);
881         SSVAL(p, 6, st.day);
882         SSVAL(p, 8, st.hour);
883         SSVAL(p, 10, st.minute);
884         SSVAL(p, 12, st.second);
885         SSVAL(p, 14, st.millisecond);
886
887         *pp = p;
888         *plen = len;
889 }
890
891 /* Convert a notification message to a struct spoolss_Notify */
892
893 static void notify_one_value(struct spoolss_notify_msg *msg,
894                              struct spoolss_Notify *data,
895                              TALLOC_CTX *mem_ctx)
896 {
897         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
898 }
899
900 static void notify_string(struct spoolss_notify_msg *msg,
901                           struct spoolss_Notify *data,
902                           TALLOC_CTX *mem_ctx)
903 {
904         /* The length of the message includes the trailing \0 */
905
906         data->data.string.size = msg->len * 2;
907         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
908         if (!data->data.string.string) {
909                 data->data.string.size = 0;
910                 return;
911         }
912 }
913
914 static void notify_system_time(struct spoolss_notify_msg *msg,
915                                struct spoolss_Notify *data,
916                                TALLOC_CTX *mem_ctx)
917 {
918         data->data.string.string = NULL;
919         data->data.string.size = 0;
920
921         if (msg->len != sizeof(time_t)) {
922                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
923                           msg->len));
924                 return;
925         }
926
927         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
928                                &data->data.string.string,
929                                &data->data.string.size);
930 }
931
932 struct notify2_message_table {
933         const char *name;
934         void (*fn)(struct spoolss_notify_msg *msg,
935                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
936 };
937
938 static struct notify2_message_table printer_notify_table[] = {
939         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
940         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
941         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
942         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
943         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
944         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
945         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
946         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
947         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
948         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
949         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
950         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
951         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
952         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
953         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
954         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
955         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
956         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
957         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
958 };
959
960 static struct notify2_message_table job_notify_table[] = {
961         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
962         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
963         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
964         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
965         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
966         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
967         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
968         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
969         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
970         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
971         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
972         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
973         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
974         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
975         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
976         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
977         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
978         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
979         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
980         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
981         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
982         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
983         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
984         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
985 };
986
987
988 /***********************************************************************
989  Allocate talloc context for container object
990  **********************************************************************/
991
992 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
993 {
994         if ( !ctr )
995                 return;
996
997         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
998
999         return;
1000 }
1001
1002 /***********************************************************************
1003  release all allocated memory and zero out structure
1004  **********************************************************************/
1005
1006 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1007 {
1008         if ( !ctr )
1009                 return;
1010
1011         if ( ctr->ctx )
1012                 talloc_destroy(ctr->ctx);
1013
1014         ZERO_STRUCTP(ctr);
1015
1016         return;
1017 }
1018
1019 /***********************************************************************
1020  **********************************************************************/
1021
1022 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1023 {
1024         if ( !ctr )
1025                 return NULL;
1026
1027         return ctr->ctx;
1028 }
1029
1030 /***********************************************************************
1031  **********************************************************************/
1032
1033 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1034 {
1035         if ( !ctr || !ctr->msg_groups )
1036                 return NULL;
1037
1038         if ( idx >= ctr->num_groups )
1039                 return NULL;
1040
1041         return &ctr->msg_groups[idx];
1042
1043 }
1044
1045 /***********************************************************************
1046  How many groups of change messages do we have ?
1047  **********************************************************************/
1048
1049 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1050 {
1051         if ( !ctr )
1052                 return 0;
1053
1054         return ctr->num_groups;
1055 }
1056
1057 /***********************************************************************
1058  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1059  **********************************************************************/
1060
1061 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1062 {
1063         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1064         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1065         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1066         int                             i, new_slot;
1067
1068         if ( !ctr || !msg )
1069                 return 0;
1070
1071         /* loop over all groups looking for a matching printer name */
1072
1073         for ( i=0; i<ctr->num_groups; i++ ) {
1074                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1075                         break;
1076         }
1077
1078         /* add a new group? */
1079
1080         if ( i == ctr->num_groups ) {
1081                 ctr->num_groups++;
1082
1083                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1084                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1085                         return 0;
1086                 }
1087                 ctr->msg_groups = groups;
1088
1089                 /* clear the new entry and set the printer name */
1090
1091                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1092                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1093         }
1094
1095         /* add the change messages; 'i' is the correct index now regardless */
1096
1097         msg_grp = &ctr->msg_groups[i];
1098
1099         msg_grp->num_msgs++;
1100
1101         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1102                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1103                 return 0;
1104         }
1105         msg_grp->msgs = msg_list;
1106
1107         new_slot = msg_grp->num_msgs-1;
1108         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1109
1110         /* need to allocate own copy of data */
1111
1112         if ( msg->len != 0 )
1113                 msg_grp->msgs[new_slot].notify.data = (char *)
1114                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1115
1116         return ctr->num_groups;
1117 }
1118
1119 static void construct_info_data(struct spoolss_Notify *info_data,
1120                                 enum spoolss_NotifyType type,
1121                                 uint16_t field, int id);
1122
1123 /***********************************************************************
1124  Send a change notication message on all handles which have a call
1125  back registered
1126  **********************************************************************/
1127
1128 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1129                                   struct printer_handle *prn_hnd,
1130                                   SPOOLSS_NOTIFY_MSG *messages,
1131                                   uint32_t num_msgs,
1132                                   struct spoolss_Notify **_notifies,
1133                                   int *_count)
1134 {
1135         struct spoolss_Notify *notifies;
1136         SPOOLSS_NOTIFY_MSG *msg;
1137         int count = 0;
1138         uint32_t id;
1139         int i;
1140
1141         notifies = talloc_zero_array(mem_ctx,
1142                                      struct spoolss_Notify, num_msgs);
1143         if (!notifies) {
1144                 return ENOMEM;
1145         }
1146
1147         for (i = 0; i < num_msgs; i++) {
1148
1149                 msg = &messages[i];
1150
1151                 /* Are we monitoring this event? */
1152
1153                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1154                         continue;
1155                 }
1156
1157                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1158                            "for printer [%s]\n",
1159                            msg->type, msg->field, prn_hnd->sharename));
1160
1161                 /*
1162                  * if the is a printer notification handle and not a job
1163                  * notification type, then set the id to 0.
1164                  * Otherwise just use what was specified in the message.
1165                  *
1166                  * When registering change notification on a print server
1167                  * handle we always need to send back the id (snum) matching
1168                  * the printer for which the change took place.
1169                  * For change notify registered on a printer handle,
1170                  * this does not matter and the id should be 0.
1171                  *
1172                  * --jerry
1173                  */
1174
1175                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1176                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1177                         id = 0;
1178                 } else {
1179                         id = msg->id;
1180                 }
1181
1182                 /* Convert unix jobid to smb jobid */
1183
1184                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1185                         id = sysjob_to_jobid(msg->id);
1186
1187                         if (id == -1) {
1188                                 DEBUG(3, ("no such unix jobid %d\n",
1189                                           msg->id));
1190                                 continue;
1191                         }
1192                 }
1193
1194                 construct_info_data(&notifies[count],
1195                                     msg->type, msg->field, id);
1196
1197                 switch(msg->type) {
1198                 case PRINTER_NOTIFY_TYPE:
1199                         if (printer_notify_table[msg->field].fn) {
1200                                 printer_notify_table[msg->field].fn(msg,
1201                                                 &notifies[count], mem_ctx);
1202                         }
1203                         break;
1204
1205                 case JOB_NOTIFY_TYPE:
1206                         if (job_notify_table[msg->field].fn) {
1207                                 job_notify_table[msg->field].fn(msg,
1208                                                 &notifies[count], mem_ctx);
1209                         }
1210                         break;
1211
1212                 default:
1213                         DEBUG(5, ("Unknown notification type %d\n",
1214                                   msg->type));
1215                         continue;
1216                 }
1217
1218                 count++;
1219         }
1220
1221         *_notifies = notifies;
1222         *_count = count;
1223
1224         return 0;
1225 }
1226
1227 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1228                                 struct printer_handle *prn_hnd,
1229                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1230 {
1231         struct spoolss_Notify *notifies;
1232         int count = 0;
1233         union spoolss_ReplyPrinterInfo info;
1234         struct spoolss_NotifyInfo info0;
1235         uint32_t reply_result;
1236         NTSTATUS status;
1237         WERROR werr;
1238         int ret;
1239
1240         /* Is there notification on this handle? */
1241         if (prn_hnd->notify.cli_chan == NULL ||
1242             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1243             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1244             prn_hnd->notify.cli_chan->active_connections == 0) {
1245                 return 0;
1246         }
1247
1248         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1249                    prn_hnd->servername, prn_hnd->sharename));
1250
1251         /* For this printer? Print servers always receive notifications. */
1252         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1253             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1254                 return 0;
1255         }
1256
1257         DEBUG(10,("Our printer\n"));
1258
1259         /* build the array of change notifications */
1260         ret = build_notify2_messages(mem_ctx, prn_hnd,
1261                                      msg_group->msgs,
1262                                      msg_group->num_msgs,
1263                                      &notifies, &count);
1264         if (ret) {
1265                 return ret;
1266         }
1267
1268         info0.version   = 0x2;
1269         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1270         info0.count     = count;
1271         info0.notifies  = notifies;
1272
1273         info.info0 = &info0;
1274
1275         status = dcerpc_spoolss_RouterReplyPrinterEx(
1276                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1277                                 mem_ctx,
1278                                 &prn_hnd->notify.cli_hnd,
1279                                 prn_hnd->notify.change, /* color */
1280                                 prn_hnd->notify.flags,
1281                                 &reply_result,
1282                                 0, /* reply_type, must be 0 */
1283                                 info, &werr);
1284         if (!NT_STATUS_IS_OK(status)) {
1285                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1286                           "failed: %s\n",
1287                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1288                           nt_errstr(status)));
1289                 werr = ntstatus_to_werror(status);
1290         } else if (!W_ERROR_IS_OK(werr)) {
1291                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1292                           "failed: %s\n",
1293                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1294                           win_errstr(werr)));
1295         }
1296         switch (reply_result) {
1297         case 0:
1298                 break;
1299         case PRINTER_NOTIFY_INFO_DISCARDED:
1300         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1301         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1302                 break;
1303         default:
1304                 break;
1305         }
1306
1307         return 0;
1308 }
1309
1310 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1311 {
1312         struct printer_handle    *p;
1313         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1314         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1315         int ret;
1316
1317         if ( !msg_group ) {
1318                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1319                 return;
1320         }
1321
1322         if (!msg_group->msgs) {
1323                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1324                 return;
1325         }
1326
1327         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1328
1329         /* loop over all printers */
1330
1331         for (p = printers_list; p; p = p->next) {
1332                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1333                 if (ret) {
1334                         goto done;
1335                 }
1336         }
1337
1338 done:
1339         DEBUG(8,("send_notify2_changes: Exit...\n"));
1340         return;
1341 }
1342
1343 /***********************************************************************
1344  **********************************************************************/
1345
1346 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1347 {
1348
1349         uint32_t tv_sec, tv_usec;
1350         size_t offset = 0;
1351
1352         /* Unpack message */
1353
1354         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1355                              msg->printer);
1356
1357         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1358                                 &tv_sec, &tv_usec,
1359                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1360
1361         if (msg->len == 0)
1362                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1363                            &msg->notify.value[0], &msg->notify.value[1]);
1364         else
1365                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1366                            &msg->len, &msg->notify.data);
1367
1368         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1369                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1370
1371         tv->tv_sec = tv_sec;
1372         tv->tv_usec = tv_usec;
1373
1374         if (msg->len == 0)
1375                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1376                           msg->notify.value[1]));
1377         else
1378                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1379
1380         return true;
1381 }
1382
1383 /********************************************************************
1384  Receive a notify2 message list
1385  ********************************************************************/
1386
1387 static void receive_notify2_message_list(struct messaging_context *msg,
1388                                          void *private_data,
1389                                          uint32_t msg_type,
1390                                          struct server_id server_id,
1391                                          DATA_BLOB *data)
1392 {
1393         size_t                  msg_count, i;
1394         char                    *buf = (char *)data->data;
1395         char                    *msg_ptr;
1396         size_t                  msg_len;
1397         SPOOLSS_NOTIFY_MSG      notify;
1398         SPOOLSS_NOTIFY_MSG_CTR  messages;
1399         int                     num_groups;
1400
1401         if (data->length < 4) {
1402                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1403                 return;
1404         }
1405
1406         msg_count = IVAL(buf, 0);
1407         msg_ptr = buf + 4;
1408
1409         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1410
1411         if (msg_count == 0) {
1412                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1413                 return;
1414         }
1415
1416         /* initialize the container */
1417
1418         ZERO_STRUCT( messages );
1419         notify_msg_ctr_init( &messages );
1420
1421         /*
1422          * build message groups for each printer identified
1423          * in a change_notify msg.  Remember that a PCN message
1424          * includes the handle returned for the srv_spoolss_replyopenprinter()
1425          * call.  Therefore messages are grouped according to printer handle.
1426          */
1427
1428         for ( i=0; i<msg_count; i++ ) {
1429                 struct timeval msg_tv;
1430
1431                 if (msg_ptr + 4 - buf > data->length) {
1432                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1433                         return;
1434                 }
1435
1436                 msg_len = IVAL(msg_ptr,0);
1437                 msg_ptr += 4;
1438
1439                 if (msg_ptr + msg_len - buf > data->length) {
1440                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1441                         return;
1442                 }
1443
1444                 /* unpack messages */
1445
1446                 ZERO_STRUCT( notify );
1447                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1448                 msg_ptr += msg_len;
1449
1450                 /* add to correct list in container */
1451
1452                 notify_msg_ctr_addmsg( &messages, &notify );
1453
1454                 /* free memory that might have been allocated by notify2_unpack_msg() */
1455
1456                 if ( notify.len != 0 )
1457                         SAFE_FREE( notify.notify.data );
1458         }
1459
1460         /* process each group of messages */
1461
1462         num_groups = notify_msg_ctr_numgroups( &messages );
1463         for ( i=0; i<num_groups; i++ )
1464                 send_notify2_changes( &messages, i );
1465
1466
1467         /* cleanup */
1468
1469         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1470                 (uint32_t)msg_count ));
1471
1472         notify_msg_ctr_destroy( &messages );
1473
1474         return;
1475 }
1476
1477 /********************************************************************
1478  Send a message to ourself about new driver being installed
1479  so we can upgrade the information for each printer bound to this
1480  driver
1481  ********************************************************************/
1482
1483 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1484                                             struct messaging_context *msg_ctx)
1485 {
1486         int len = strlen(drivername);
1487
1488         if (!len)
1489                 return false;
1490
1491         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1492                 drivername));
1493
1494         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1495                            MSG_PRINTER_DRVUPGRADE,
1496                            (const uint8_t *)drivername, len+1);
1497
1498         return true;
1499 }
1500
1501 void srv_spoolss_cleanup(void)
1502 {
1503         struct printer_session_counter *session_counter;
1504
1505         for (session_counter = counter_list;
1506              session_counter != NULL;
1507              session_counter = counter_list) {
1508                 DLIST_REMOVE(counter_list, session_counter);
1509                 TALLOC_FREE(session_counter);
1510         }
1511 }
1512
1513 /**********************************************************************
1514  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1515  over all printers, upgrading ones as necessary
1516  This is now *ONLY* called inside the background lpq updater. JRA.
1517  **********************************************************************/
1518
1519 void do_drv_upgrade_printer(struct messaging_context *msg,
1520                             void *private_data,
1521                             uint32_t msg_type,
1522                             struct server_id server_id,
1523                             DATA_BLOB *data)
1524 {
1525         TALLOC_CTX *tmp_ctx;
1526         const struct auth_session_info *session_info = get_session_info_system();
1527         struct spoolss_PrinterInfo2 *pinfo2;
1528         WERROR result;
1529         const char *drivername;
1530         int snum;
1531         int n_services = lp_numservices();
1532         struct dcerpc_binding_handle *b = NULL;
1533
1534         tmp_ctx = talloc_new(NULL);
1535         if (!tmp_ctx) return;
1536
1537         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1538         if (!drivername) {
1539                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1540                 goto done;
1541         }
1542
1543         DEBUG(10, ("do_drv_upgrade_printer: "
1544                    "Got message for new driver [%s]\n", drivername));
1545
1546         /* Iterate the printer list */
1547
1548         for (snum = 0; snum < n_services; snum++) {
1549                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1550                         continue;
1551                 }
1552
1553                 /* ignore [printers] share */
1554                 if (strequal(lp_const_servicename(snum), "printers")) {
1555                         continue;
1556                 }
1557
1558                 if (b == NULL) {
1559                         result = winreg_printer_binding_handle(tmp_ctx,
1560                                                                session_info,
1561                                                                msg,
1562                                                                &b);
1563                         if (!W_ERROR_IS_OK(result)) {
1564                                 break;
1565                         }
1566                 }
1567
1568                 result = winreg_get_printer(tmp_ctx, b,
1569                                             lp_const_servicename(snum),
1570                                             &pinfo2);
1571
1572                 if (!W_ERROR_IS_OK(result)) {
1573                         continue;
1574                 }
1575
1576                 if (!pinfo2->drivername) {
1577                         continue;
1578                 }
1579
1580                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1581                         continue;
1582                 }
1583
1584                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1585
1586                 /* all we care about currently is the change_id */
1587                 result = winreg_printer_update_changeid(tmp_ctx, b,
1588                                                         pinfo2->printername);
1589
1590                 if (!W_ERROR_IS_OK(result)) {
1591                         DEBUG(3, ("do_drv_upgrade_printer: "
1592                                   "Failed to update changeid [%s]\n",
1593                                   win_errstr(result)));
1594                 }
1595         }
1596
1597         /* all done */
1598 done:
1599         talloc_free(tmp_ctx);
1600 }
1601
1602 /********************************************************************
1603  Update the cache for all printq's with a registered client
1604  connection
1605  ********************************************************************/
1606
1607 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1608 {
1609         struct printer_handle *printer = printers_list;
1610         int snum;
1611
1612         /* loop through all printers and update the cache where
1613            a client is connected */
1614         while (printer) {
1615                 if ((printer->printer_type == SPLHND_PRINTER) &&
1616                     ((printer->notify.cli_chan != NULL) &&
1617                      (printer->notify.cli_chan->active_connections > 0))) {
1618                         snum = print_queue_snum(printer->sharename);
1619                         print_queue_status(msg_ctx, snum, NULL, NULL);
1620                 }
1621
1622                 printer = printer->next;
1623         }
1624
1625         return;
1626 }
1627
1628 /****************************************************************
1629  _spoolss_OpenPrinter
1630 ****************************************************************/
1631
1632 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1633                             struct spoolss_OpenPrinter *r)
1634 {
1635         struct spoolss_OpenPrinterEx e;
1636         WERROR werr;
1637
1638         ZERO_STRUCT(e.in.userlevel);
1639
1640         e.in.printername        = r->in.printername;
1641         e.in.datatype           = r->in.datatype;
1642         e.in.devmode_ctr        = r->in.devmode_ctr;
1643         e.in.access_mask        = r->in.access_mask;
1644         e.in.level              = 0;
1645
1646         e.out.handle            = r->out.handle;
1647
1648         werr = _spoolss_OpenPrinterEx(p, &e);
1649
1650         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1651                 /* OpenPrinterEx returns this for a bad
1652                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1653                  * instead.
1654                  */
1655                 werr = WERR_INVALID_PRINTER_NAME;
1656         }
1657
1658         return werr;
1659 }
1660
1661 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1662                               struct spoolss_DeviceMode *orig,
1663                               struct spoolss_DeviceMode **dest)
1664 {
1665         struct spoolss_DeviceMode *dm;
1666
1667         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1668         if (!dm) {
1669                 return WERR_NOMEM;
1670         }
1671
1672         /* copy all values, then duplicate strings and structs */
1673         *dm = *orig;
1674
1675         dm->devicename = talloc_strdup(dm, orig->devicename);
1676         if (!dm->devicename) {
1677                 return WERR_NOMEM;
1678         }
1679         dm->formname = talloc_strdup(dm, orig->formname);
1680         if (!dm->formname) {
1681                 return WERR_NOMEM;
1682         }
1683         if (orig->driverextra_data.data) {
1684                 dm->driverextra_data.data =
1685                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1686                                         orig->driverextra_data.length);
1687                 if (!dm->driverextra_data.data) {
1688                         return WERR_NOMEM;
1689                 }
1690         }
1691
1692         *dest = dm;
1693         return WERR_OK;
1694 }
1695
1696 /****************************************************************
1697  _spoolss_OpenPrinterEx
1698 ****************************************************************/
1699
1700 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1701                               struct spoolss_OpenPrinterEx *r)
1702 {
1703         int snum;
1704         char *raddr;
1705         char *rhost;
1706         struct printer_handle *Printer=NULL;
1707         WERROR result;
1708         int rc;
1709
1710         if (!r->in.printername) {
1711                 return WERR_INVALID_PARAM;
1712         }
1713
1714         if (!*r->in.printername) {
1715                 return WERR_INVALID_PARAM;
1716         }
1717
1718         if (r->in.level > 3) {
1719                 return WERR_INVALID_PARAM;
1720         }
1721         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1722             (r->in.level == 2 && !r->in.userlevel.level2) ||
1723             (r->in.level == 3 && !r->in.userlevel.level3)) {
1724                 return WERR_INVALID_PARAM;
1725         }
1726
1727         /*
1728          * The printcap printer share inventory is updated on client
1729          * enumeration. For clients that do not perform enumeration prior to
1730          * access, such as cupssmbadd, we reinitialise the printer share
1731          * inventory on open as well.
1732          */
1733         become_root();
1734         delete_and_reload_printers(server_event_context(), p->msg_ctx);
1735         unbecome_root();
1736
1737         /* some sanity check because you can open a printer or a print server */
1738         /* aka: \\server\printer or \\server */
1739
1740         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1741
1742         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1743         if (!W_ERROR_IS_OK(result)) {
1744                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1745                         "for printer %s\n", r->in.printername));
1746                 ZERO_STRUCTP(r->out.handle);
1747                 return result;
1748         }
1749
1750         Printer = find_printer_index_by_hnd(p, r->out.handle);
1751         if ( !Printer ) {
1752                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1753                         "handle we created for printer %s\n", r->in.printername));
1754                 close_printer_handle(p, r->out.handle);
1755                 ZERO_STRUCTP(r->out.handle);
1756                 return WERR_INVALID_PARAM;
1757         }
1758
1759         /*
1760          * First case: the user is opening the print server:
1761          *
1762          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1763          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1764          *
1765          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1766          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1767          * or if the user is listed in the smb.conf printer admin parameter.
1768          *
1769          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1770          * client view printer folder, but does not show the MSAPW.
1771          *
1772          * Note: this test needs code to check access rights here too. Jeremy
1773          * could you look at this?
1774          *
1775          * Second case: the user is opening a printer:
1776          * NT doesn't let us connect to a printer if the connecting user
1777          * doesn't have print permission.
1778          *
1779          * Third case: user is opening a Port Monitor
1780          * access checks same as opening a handle to the print server.
1781          */
1782
1783         switch (Printer->printer_type )
1784         {
1785         case SPLHND_SERVER:
1786         case SPLHND_PORTMON_TCP:
1787         case SPLHND_PORTMON_LOCAL:
1788                 /* Printserver handles use global struct... */
1789
1790                 snum = -1;
1791
1792                 /* Map standard access rights to object specific access rights */
1793
1794                 se_map_standard(&r->in.access_mask,
1795                                 &printserver_std_mapping);
1796
1797                 /* Deny any object specific bits that don't apply to print
1798                    servers (i.e printer and job specific bits) */
1799
1800                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1801
1802                 if (r->in.access_mask &
1803                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1804                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1805                         close_printer_handle(p, r->out.handle);
1806                         ZERO_STRUCTP(r->out.handle);
1807                         return WERR_ACCESS_DENIED;
1808                 }
1809
1810                 /* Allow admin access */
1811
1812                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1813                 {
1814                         if (!lp_ms_add_printer_wizard()) {
1815                                 close_printer_handle(p, r->out.handle);
1816                                 ZERO_STRUCTP(r->out.handle);
1817                                 return WERR_ACCESS_DENIED;
1818                         }
1819
1820                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1821                            and not a printer admin, then fail */
1822
1823                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1824                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1825                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1826                                                 p->session_info->security_token)) {
1827                                 close_printer_handle(p, r->out.handle);
1828                                 ZERO_STRUCTP(r->out.handle);
1829                                 DEBUG(3,("access DENIED as user is not root, "
1830                                         "has no printoperator privilege, "
1831                                         "not a member of the printoperator builtin group and "
1832                                         "is not in printer admin list"));
1833                                 return WERR_ACCESS_DENIED;
1834                         }
1835
1836                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1837                 }
1838                 else
1839                 {
1840                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1841                 }
1842
1843                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1844                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1845
1846                 /* We fall through to return WERR_OK */
1847                 break;
1848
1849         case SPLHND_PRINTER:
1850                 /* NT doesn't let us connect to a printer if the connecting user
1851                    doesn't have print permission.  */
1852
1853                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1854                         close_printer_handle(p, r->out.handle);
1855                         ZERO_STRUCTP(r->out.handle);
1856                         return WERR_BADFID;
1857                 }
1858
1859                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1860                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1861                 }
1862
1863                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1864
1865                 /* map an empty access mask to the minimum access mask */
1866                 if (r->in.access_mask == 0x0)
1867                         r->in.access_mask = PRINTER_ACCESS_USE;
1868
1869                 /*
1870                  * If we are not serving the printer driver for this printer,
1871                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1872                  * will keep NT clients happy  --jerry
1873                  */
1874
1875                 if (lp_use_client_driver(snum)
1876                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1877                 {
1878                         r->in.access_mask = PRINTER_ACCESS_USE;
1879                 }
1880
1881                 /* check smb.conf parameters and the the sec_desc */
1882                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1883                                                          p->mem_ctx);
1884                 if (raddr == NULL) {
1885                         return WERR_NOMEM;
1886                 }
1887
1888                 rc = get_remote_hostname(p->remote_address,
1889                                          &rhost,
1890                                          p->mem_ctx);
1891                 if (rc < 0) {
1892                         return WERR_NOMEM;
1893                 }
1894                 if (strequal(rhost, "UNKNOWN")) {
1895                         rhost = raddr;
1896                 }
1897
1898                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1899                                   rhost, raddr)) {
1900                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1901                         ZERO_STRUCTP(r->out.handle);
1902                         return WERR_ACCESS_DENIED;
1903                 }
1904
1905                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1906                                    p->session_info->security_token, snum) ||
1907                     !print_access_check(p->session_info,
1908                                         p->msg_ctx,
1909                                         snum,
1910                                         r->in.access_mask)) {
1911                         DEBUG(3, ("access DENIED for printer open\n"));
1912                         close_printer_handle(p, r->out.handle);
1913                         ZERO_STRUCTP(r->out.handle);
1914                         return WERR_ACCESS_DENIED;
1915                 }
1916
1917                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1918                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1919                         close_printer_handle(p, r->out.handle);
1920                         ZERO_STRUCTP(r->out.handle);
1921                         return WERR_ACCESS_DENIED;
1922                 }
1923
1924                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1925                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1926                 else
1927                         r->in.access_mask = PRINTER_ACCESS_USE;
1928
1929                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1930                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1931
1932                 winreg_create_printer_internal(p->mem_ctx,
1933                                       get_session_info_system(),
1934                                       p->msg_ctx,
1935                                       lp_const_servicename(snum));
1936
1937                 break;
1938
1939         default:
1940                 /* sanity check to prevent programmer error */
1941                 ZERO_STRUCTP(r->out.handle);
1942                 return WERR_BADFID;
1943         }
1944
1945         Printer->access_granted = r->in.access_mask;
1946
1947         /*
1948          * If the client sent a devmode in the OpenPrinter() call, then
1949          * save it here in case we get a job submission on this handle
1950          */
1951
1952          if ((Printer->printer_type != SPLHND_SERVER)
1953           && (r->in.devmode_ctr.devmode != NULL)) {
1954                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1955                                 &Printer->devmode);
1956          }
1957
1958         return WERR_OK;
1959 }
1960
1961 /****************************************************************
1962  _spoolss_ClosePrinter
1963 ****************************************************************/
1964
1965 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1966                              struct spoolss_ClosePrinter *r)
1967 {
1968         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1969
1970         if (Printer && Printer->document_started) {
1971                 struct spoolss_EndDocPrinter e;
1972
1973                 e.in.handle = r->in.handle;
1974
1975                 _spoolss_EndDocPrinter(p, &e);
1976         }
1977
1978         if (!close_printer_handle(p, r->in.handle))
1979                 return WERR_BADFID;
1980
1981         /* clear the returned printer handle.  Observed behavior
1982            from Win2k server.  Don't think this really matters.
1983            Previous code just copied the value of the closed
1984            handle.    --jerry */
1985
1986         ZERO_STRUCTP(r->out.handle);
1987
1988         return WERR_OK;
1989 }
1990
1991 /****************************************************************
1992  _spoolss_DeletePrinter
1993 ****************************************************************/
1994
1995 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1996                               struct spoolss_DeletePrinter *r)
1997 {
1998         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1999         WERROR result;
2000         int snum;
2001
2002         if (Printer && Printer->document_started) {
2003                 struct spoolss_EndDocPrinter e;
2004
2005                 e.in.handle = r->in.handle;
2006
2007                 _spoolss_EndDocPrinter(p, &e);
2008         }
2009
2010         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2011                 winreg_delete_printer_key_internal(p->mem_ctx,
2012                                           get_session_info_system(),
2013                                           p->msg_ctx,
2014                                           lp_const_servicename(snum),
2015                                           "");
2016         }
2017
2018         result = delete_printer_handle(p, r->in.handle);
2019
2020         return result;
2021 }
2022
2023 /*******************************************************************
2024  * static function to lookup the version id corresponding to an
2025  * long architecture string
2026  ******************************************************************/
2027
2028 static const struct print_architecture_table_node archi_table[]= {
2029
2030         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2031         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2032         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2033         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2034         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2035         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2036         {"Windows x64",          SPL_ARCH_X64,          3 },
2037         {NULL,                   "",            -1 }
2038 };
2039
2040 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2041                                    SPOOLSS_DRIVER_VERSION_NT35,
2042                                    SPOOLSS_DRIVER_VERSION_NT4,
2043                                    SPOOLSS_DRIVER_VERSION_200X,
2044                                    -1};
2045
2046 static int get_version_id(const char *arch)
2047 {
2048         int i;
2049
2050         for (i=0; archi_table[i].long_archi != NULL; i++)
2051         {
2052                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2053                         return (archi_table[i].version);
2054         }
2055
2056         return -1;
2057 }
2058
2059 /****************************************************************
2060  _spoolss_DeletePrinterDriver
2061 ****************************************************************/
2062
2063 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2064                                     struct spoolss_DeletePrinterDriver *r)
2065 {
2066
2067         struct spoolss_DriverInfo8 *info = NULL;
2068         int                             version;
2069         WERROR                          status;
2070         struct dcerpc_binding_handle *b;
2071         TALLOC_CTX *tmp_ctx = NULL;
2072         int i;
2073         bool found;
2074
2075         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2076            and not a printer admin, then fail */
2077
2078         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2079             !security_token_has_privilege(p->session_info->security_token,
2080                                           SEC_PRIV_PRINT_OPERATOR)) {
2081                 return WERR_ACCESS_DENIED;
2082         }
2083
2084         /* check that we have a valid driver name first */
2085
2086         if ((version = get_version_id(r->in.architecture)) == -1) {
2087                 return WERR_INVALID_ENVIRONMENT;
2088         }
2089
2090         tmp_ctx = talloc_new(p->mem_ctx);
2091         if (!tmp_ctx) {
2092                 return WERR_NOMEM;
2093         }
2094
2095         status = winreg_printer_binding_handle(tmp_ctx,
2096                                                get_session_info_system(),
2097                                                p->msg_ctx,
2098                                                &b);
2099         if (!W_ERROR_IS_OK(status)) {
2100                 goto done;
2101         }
2102
2103         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2104                 status = winreg_get_driver(tmp_ctx, b,
2105                                            r->in.architecture, r->in.driver,
2106                                            drv_cversion[i], &info);
2107                 if (!W_ERROR_IS_OK(status)) {
2108                         DEBUG(5, ("skipping del of driver with version %d\n",
2109                                   drv_cversion[i]));
2110                         continue;
2111                 }
2112                 found = true;
2113
2114                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2115                         status = WERR_PRINTER_DRIVER_IN_USE;
2116                         goto done;
2117                 }
2118
2119                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2120                 if (!W_ERROR_IS_OK(status)) {
2121                         DEBUG(0, ("failed del of driver with version %d\n",
2122                                   drv_cversion[i]));
2123                         goto done;
2124                 }
2125         }
2126         if (found == false) {
2127                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2128                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2129         } else {
2130                 status = WERR_OK;
2131         }
2132
2133 done:
2134         talloc_free(tmp_ctx);
2135
2136         return status;
2137 }
2138
2139 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2140                                   struct pipes_struct *p,
2141                                   struct spoolss_DeletePrinterDriverEx *r,
2142                                   struct dcerpc_binding_handle *b,
2143                                   struct spoolss_DriverInfo8 *info)
2144 {
2145         WERROR status;
2146         bool delete_files;
2147
2148         if (printer_driver_in_use(mem_ctx, b, info)) {
2149                 status = WERR_PRINTER_DRIVER_IN_USE;
2150                 goto done;
2151         }
2152
2153         /*
2154          * we have a couple of cases to consider.
2155          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2156          *     then the delete should fail if **any** files overlap with
2157          *     other drivers
2158          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2159          *     non-overlapping files
2160          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2161          *     are set, then do not delete any files
2162          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2163          */
2164
2165         delete_files = r->in.delete_flags
2166                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2167
2168
2169         if (delete_files) {
2170                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2171                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2172                         status = WERR_PRINTER_DRIVER_IN_USE;
2173                         goto done;
2174                 }
2175                 /*
2176                  * printer_driver_files_in_use() has trimmed overlapping files
2177                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2178                  */
2179         }
2180
2181
2182         status = winreg_del_driver(mem_ctx, b, info, info->version);
2183         if (!W_ERROR_IS_OK(status)) {
2184                 goto done;
2185         }
2186
2187         /*
2188          * now delete any associated files if delete_files is
2189          * true. Even if this part failes, we return succes
2190          * because the driver doesn not exist any more
2191          */
2192         if (delete_files) {
2193                 delete_driver_files(p->session_info, info);
2194         }
2195
2196 done:
2197         return status;
2198 }
2199
2200 /****************************************************************
2201  _spoolss_DeletePrinterDriverEx
2202 ****************************************************************/
2203
2204 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2205                                       struct spoolss_DeletePrinterDriverEx *r)
2206 {
2207         struct spoolss_DriverInfo8 *info = NULL;
2208         WERROR                          status;
2209         struct dcerpc_binding_handle *b;
2210         TALLOC_CTX *tmp_ctx = NULL;
2211         int i;
2212         bool found;
2213
2214         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2215            and not a printer admin, then fail */
2216
2217         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2218             !security_token_has_privilege(p->session_info->security_token,
2219                                           SEC_PRIV_PRINT_OPERATOR)) {
2220                 return WERR_ACCESS_DENIED;
2221         }
2222
2223         /* check that we have a valid driver name first */
2224         if (get_version_id(r->in.architecture) == -1) {
2225                 /* this is what NT returns */
2226                 return WERR_INVALID_ENVIRONMENT;
2227         }
2228
2229         tmp_ctx = talloc_new(p->mem_ctx);
2230         if (!tmp_ctx) {
2231                 return WERR_NOMEM;
2232         }
2233
2234         status = winreg_printer_binding_handle(tmp_ctx,
2235                                                get_session_info_system(),
2236                                                p->msg_ctx,
2237                                                &b);
2238         if (!W_ERROR_IS_OK(status)) {
2239                 goto done;
2240         }
2241
2242         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2243                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2244                  && (drv_cversion[i] != r->in.version)) {
2245                         continue;
2246                 }
2247
2248                 /* check if a driver with this version exists before delete */
2249                 status = winreg_get_driver(tmp_ctx, b,
2250                                            r->in.architecture, r->in.driver,
2251                                            drv_cversion[i], &info);
2252                 if (!W_ERROR_IS_OK(status)) {
2253                         DEBUG(5, ("skipping del of driver with version %d\n",
2254                                   drv_cversion[i]));
2255                         continue;
2256                 }
2257                 found = true;
2258
2259                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2260                 if (!W_ERROR_IS_OK(status)) {
2261                         DEBUG(0, ("failed to delete driver with version %d\n",
2262                                   drv_cversion[i]));
2263                         goto done;
2264                 }
2265         }
2266         if (found == false) {
2267                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2268                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2269         } else {
2270                 status = WERR_OK;
2271         }
2272
2273 done:
2274         talloc_free(tmp_ctx);
2275         return status;
2276 }
2277
2278
2279 /********************************************************************
2280  GetPrinterData on a printer server Handle.
2281 ********************************************************************/
2282
2283 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2284                                             const char *value,
2285                                             enum winreg_Type *type,
2286                                             union spoolss_PrinterData *data)
2287 {
2288         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2289
2290         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2291                 *type = REG_DWORD;
2292                 SIVAL(&data->value, 0, 0x00);
2293                 return WERR_OK;
2294         }
2295
2296         if (!strcasecmp_m(value, "BeepEnabled")) {
2297                 *type = REG_DWORD;
2298                 SIVAL(&data->value, 0, 0x00);
2299                 return WERR_OK;
2300         }
2301
2302         if (!strcasecmp_m(value, "EventLog")) {
2303                 *type = REG_DWORD;
2304                 /* formally was 0x1b */
2305                 SIVAL(&data->value, 0, 0x00);
2306                 return WERR_OK;
2307         }
2308
2309         if (!strcasecmp_m(value, "NetPopup")) {
2310                 *type = REG_DWORD;
2311                 SIVAL(&data->value, 0, 0x00);
2312                 return WERR_OK;
2313         }
2314
2315         if (!strcasecmp_m(value, "MajorVersion")) {
2316                 *type = REG_DWORD;
2317
2318                 /* Windows NT 4.0 seems to not allow uploading of drivers
2319                    to a server that reports 0x3 as the MajorVersion.
2320                    need to investigate more how Win2k gets around this .
2321                    -- jerry */
2322
2323                 if (RA_WINNT == get_remote_arch()) {
2324                         SIVAL(&data->value, 0, 0x02);
2325                 } else {
2326                         SIVAL(&data->value, 0, 0x03);
2327                 }
2328
2329                 return WERR_OK;
2330         }
2331
2332         if (!strcasecmp_m(value, "MinorVersion")) {
2333                 *type = REG_DWORD;
2334                 SIVAL(&data->value, 0, 0x00);
2335                 return WERR_OK;
2336         }
2337
2338         /* REG_BINARY
2339          *  uint32_t size        = 0x114
2340          *  uint32_t major       = 5
2341          *  uint32_t minor       = [0|1]
2342          *  uint32_t build       = [2195|2600]
2343          *  extra unicode string = e.g. "Service Pack 3"
2344          */
2345         if (!strcasecmp_m(value, "OSVersion")) {
2346                 DATA_BLOB blob;
2347                 enum ndr_err_code ndr_err;
2348                 struct spoolss_OSVersion os;
2349
2350                 os.major                = 5;    /* Windows 2000 == 5.0 */
2351                 os.minor                = 0;
2352                 os.build                = 2195; /* build */
2353                 os.extra_string         = "";   /* leave extra string empty */
2354
2355                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2356                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2357                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2358                         return WERR_GENERAL_FAILURE;
2359                 }
2360
2361                 *type = REG_BINARY;
2362                 data->binary = blob;
2363
2364                 return WERR_OK;
2365         }
2366
2367
2368         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2369                 *type = REG_SZ;
2370
2371                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2372                 W_ERROR_HAVE_NO_MEMORY(data->string);
2373
2374                 return WERR_OK;
2375         }
2376
2377         if (!strcasecmp_m(value, "Architecture")) {
2378                 *type = REG_SZ;
2379                 data->string = talloc_strdup(mem_ctx,
2380                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2381                 W_ERROR_HAVE_NO_MEMORY(data->string);
2382
2383                 return WERR_OK;
2384         }
2385
2386         if (!strcasecmp_m(value, "DsPresent")) {
2387                 *type = REG_DWORD;
2388
2389                 /* only show the publish check box if we are a
2390                    member of a AD domain */
2391
2392                 if (lp_security() == SEC_ADS) {
2393                         SIVAL(&data->value, 0, 0x01);
2394                 } else {
2395                         SIVAL(&data->value, 0, 0x00);
2396                 }
2397                 return WERR_OK;
2398         }
2399
2400         if (!strcasecmp_m(value, "DNSMachineName")) {
2401                 const char *hostname = get_mydnsfullname();
2402
2403                 if (!hostname) {
2404                         return WERR_BADFILE;
2405                 }
2406
2407                 *type = REG_SZ;
2408                 data->string = talloc_strdup(mem_ctx, hostname);
2409                 W_ERROR_HAVE_NO_MEMORY(data->string);
2410
2411                 return WERR_OK;
2412         }
2413
2414         *type = REG_NONE;
2415
2416         return WERR_INVALID_PARAM;
2417 }
2418
2419 /****************************************************************
2420  _spoolss_GetPrinterData
2421 ****************************************************************/
2422
2423 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2424                                struct spoolss_GetPrinterData *r)
2425 {
2426         struct spoolss_GetPrinterDataEx r2;
2427
2428         r2.in.handle            = r->in.handle;
2429         r2.in.key_name          = "PrinterDriverData";
2430         r2.in.value_name        = r->in.value_name;
2431         r2.in.offered           = r->in.offered;
2432         r2.out.type             = r->out.type;
2433         r2.out.data             = r->out.data;
2434         r2.out.needed           = r->out.needed;
2435
2436         return _spoolss_GetPrinterDataEx(p, &r2);
2437 }
2438
2439 /*********************************************************
2440  Connect to the client machine.
2441 **********************************************************/
2442
2443 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2444                         struct sockaddr_storage *client_ss, const char *remote_machine)
2445 {
2446         NTSTATUS ret;
2447         struct cli_state *the_cli;
2448         struct sockaddr_storage rm_addr;
2449         char addr[INET6_ADDRSTRLEN];
2450
2451         if ( is_zero_addr(client_ss) ) {
2452                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2453                         remote_machine));
2454                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2455                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2456                         return false;
2457                 }
2458                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2459         } else {
2460                 rm_addr = *client_ss;
2461                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2462                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2463                         addr));
2464         }
2465
2466         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2467                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2468                         addr));
2469                 return false;
2470         }
2471
2472         /* setup the connection */
2473         ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2474                 &rm_addr, 0, "IPC$", "IPC",
2475                 "", /* username */
2476                 "", /* domain */
2477                 "", /* password */
2478                 0, lp_client_signing());
2479
2480         if ( !NT_STATUS_IS_OK( ret ) ) {
2481                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2482                         remote_machine ));
2483                 return false;
2484         }
2485
2486         if ( smbXcli_conn_protocol(the_cli->conn) != PROTOCOL_NT1 ) {
2487                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2488                 cli_shutdown(the_cli);
2489                 return false;
2490         }
2491
2492         /*
2493          * Ok - we have an anonymous connection to the IPC$ share.
2494          * Now start the NT Domain stuff :-).
2495          */
2496
2497         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2498         if (!NT_STATUS_IS_OK(ret)) {
2499                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2500                         remote_machine, nt_errstr(ret)));
2501                 cli_shutdown(the_cli);
2502                 return false;
2503         }
2504
2505         return true;
2506 }
2507
2508 /***************************************************************************
2509  Connect to the client.
2510 ****************************************************************************/
2511
2512 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2513                                         uint32_t localprinter,
2514                                         enum winreg_Type type,
2515                                         struct policy_handle *handle,
2516                                         struct notify_back_channel **_chan,
2517                                         struct sockaddr_storage *client_ss,
2518                                         struct messaging_context *msg_ctx)
2519 {
2520         WERROR result;
2521         NTSTATUS status;
2522         struct notify_back_channel *chan;
2523
2524         for (chan = back_channels; chan; chan = chan->next) {
2525                 if (memcmp(&chan->client_address, client_ss,
2526                            sizeof(struct sockaddr_storage)) == 0) {
2527                         break;
2528                 }
2529         }
2530
2531         /*
2532          * If it's the first connection, contact the client
2533          * and connect to the IPC$ share anonymously
2534          */
2535         if (!chan) {
2536                 fstring unix_printer;
2537
2538                 /* the +2 is to strip the leading 2 backslashs */
2539                 fstrcpy(unix_printer, printer + 2);
2540
2541                 chan = talloc_zero(NULL, struct notify_back_channel);
2542                 if (!chan) {
2543                         return false;
2544                 }
2545                 chan->client_address = *client_ss;
2546
2547                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2548                         TALLOC_FREE(chan);
2549                         return false;
2550                 }
2551
2552                 DLIST_ADD(back_channels, chan);
2553
2554                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2555                                    receive_notify2_message_list);
2556         }
2557
2558         if (chan->cli_pipe == NULL ||
2559             chan->cli_pipe->binding_handle == NULL) {
2560                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2561                         "NULL %s for printer %s\n",
2562                         chan->cli_pipe == NULL ?
2563                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2564                         printer));
2565                 return false;
2566         }
2567
2568         /*
2569          * Tell the specific printing tdb we want messages for this printer
2570          * by registering our PID.
2571          */
2572
2573         if (!print_notify_register_pid(snum)) {
2574                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2575                           printer));
2576         }
2577
2578         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2579                                                  talloc_tos(),
2580                                                  printer,
2581                                                  localprinter,
2582                                                  type,
2583                                                  0,
2584                                                  NULL,
2585                                                  handle,
2586                                                  &result);
2587         if (!NT_STATUS_IS_OK(status)) {
2588                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2589                 result = ntstatus_to_werror(status);
2590         } else if (!W_ERROR_IS_OK(result)) {
2591                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2592         }
2593
2594         chan->active_connections++;
2595         *_chan = chan;
2596
2597         return (W_ERROR_IS_OK(result));
2598 }
2599
2600 /****************************************************************
2601  ****************************************************************/
2602
2603 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2604                                                              const struct spoolss_NotifyOption *r)
2605 {
2606         struct spoolss_NotifyOption *option;
2607         uint32_t i,k;
2608
2609         if (!r) {
2610                 return NULL;
2611         }
2612
2613         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2614         if (!option) {
2615                 return NULL;
2616         }
2617
2618         *option = *r;
2619
2620         if (!option->count) {
2621                 return option;
2622         }
2623
2624         option->types = talloc_zero_array(option,
2625                 struct spoolss_NotifyOptionType, option->count);
2626         if (!option->types) {
2627                 talloc_free(option);
2628                 return NULL;
2629         }
2630
2631         for (i=0; i < option->count; i++) {
2632                 option->types[i] = r->types[i];
2633
2634                 if (option->types[i].count) {
2635                         option->types[i].fields = talloc_zero_array(option,
2636                                 union spoolss_Field, option->types[i].count);
2637                         if (!option->types[i].fields) {
2638                                 talloc_free(option);
2639                                 return NULL;
2640                         }
2641                         for (k=0; k<option->types[i].count; k++) {
2642                                 option->types[i].fields[k] =
2643                                         r->types[i].fields[k];
2644                         }
2645                 }
2646         }
2647
2648         return option;
2649 }
2650
2651 /****************************************************************
2652  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2653  *
2654  * before replying OK: status=0 a rpc call is made to the workstation
2655  * asking ReplyOpenPrinter
2656  *
2657  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2658  * called from api_spoolss_rffpcnex
2659 ****************************************************************/
2660
2661 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2662                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2663 {
2664         int snum = -1;
2665         struct spoolss_NotifyOption *option = r->in.notify_options;
2666         struct sockaddr_storage client_ss;
2667         ssize_t client_len;
2668
2669         /* store the notify value in the printer struct */
2670
2671         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2672
2673         if (!Printer) {
2674                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2675                         "Invalid handle (%s:%u:%u).\n",
2676                         OUR_HANDLE(r->in.handle)));
2677                 return WERR_BADFID;
2678         }
2679
2680         Printer->notify.flags           = r->in.flags;
2681         Printer->notify.options         = r->in.options;
2682         Printer->notify.printerlocal    = r->in.printer_local;
2683         Printer->notify.msg_ctx         = p->msg_ctx;
2684
2685         TALLOC_FREE(Printer->notify.option);
2686         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2687
2688         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2689
2690         /* Connect to the client machine and send a ReplyOpenPrinter */
2691
2692         if ( Printer->printer_type == SPLHND_SERVER)
2693                 snum = -1;
2694         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2695                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2696                 return WERR_BADFID;
2697
2698         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2699                   "remote_address is %s\n",
2700                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2701
2702         if (!lp_print_notify_backchannel(snum)) {
2703                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2704                         "backchannel disabled\n"));
2705                 return WERR_SERVER_UNAVAILABLE;
2706         }
2707
2708         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2709                                                   (struct sockaddr *) &client_ss,
2710                                                   sizeof(struct sockaddr_storage));
2711         if (client_len < 0) {
2712                 return WERR_NOMEM;
2713         }
2714
2715         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2716                                         Printer->notify.printerlocal, REG_SZ,
2717                                         &Printer->notify.cli_hnd,
2718                                         &Printer->notify.cli_chan,
2719                                         &client_ss, p->msg_ctx)) {
2720                 return WERR_SERVER_UNAVAILABLE;
2721         }
2722
2723         return WERR_OK;
2724 }
2725
2726 /*******************************************************************
2727  * fill a notify_info_data with the servername
2728  ********************************************************************/
2729
2730 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2731                                        int snum,
2732                                        struct spoolss_Notify *data,
2733                                        print_queue_struct *queue,
2734                                        struct spoolss_PrinterInfo2 *pinfo2,
2735                                        TALLOC_CTX *mem_ctx)
2736 {
2737         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2738 }
2739
2740 /*******************************************************************
2741  * fill a notify_info_data with the printername (not including the servername).
2742  ********************************************************************/
2743
2744 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2745                                         int snum,
2746                                         struct spoolss_Notify *data,
2747                                         print_queue_struct *queue,
2748                                         struct spoolss_PrinterInfo2 *pinfo2,
2749                                         TALLOC_CTX *mem_ctx)
2750 {
2751         /* the notify name should not contain the \\server\ part */
2752         const char *p = strrchr(pinfo2->printername, '\\');
2753
2754         if (!p) {
2755                 p = pinfo2->printername;
2756         } else {
2757                 p++;
2758         }
2759
2760         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2761 }
2762
2763 /*******************************************************************
2764  * fill a notify_info_data with the servicename
2765  ********************************************************************/
2766
2767 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2768                                       int snum,
2769                                       struct spoolss_Notify *data,
2770                                       print_queue_struct *queue,
2771                                       struct spoolss_PrinterInfo2 *pinfo2,
2772                                       TALLOC_CTX *mem_ctx)
2773 {
2774         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2775 }
2776
2777 /*******************************************************************
2778  * fill a notify_info_data with the port name
2779  ********************************************************************/
2780
2781 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2782                                      int snum,
2783                                      struct spoolss_Notify *data,
2784                                      print_queue_struct *queue,
2785                                      struct spoolss_PrinterInfo2 *pinfo2,
2786                                      TALLOC_CTX *mem_ctx)
2787 {
2788         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2789 }
2790
2791 /*******************************************************************
2792  * fill a notify_info_data with the printername
2793  * but it doesn't exist, have to see what to do
2794  ********************************************************************/
2795
2796 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2797                                        int snum,
2798                                        struct spoolss_Notify *data,
2799                                        print_queue_struct *queue,
2800                                        struct spoolss_PrinterInfo2 *pinfo2,
2801                                        TALLOC_CTX *mem_ctx)
2802 {
2803         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2804 }
2805
2806 /*******************************************************************
2807  * fill a notify_info_data with the comment
2808  ********************************************************************/
2809
2810 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2811                                    int snum,
2812                                    struct spoolss_Notify *data,
2813                                    print_queue_struct *queue,
2814                                    struct spoolss_PrinterInfo2 *pinfo2,
2815                                    TALLOC_CTX *mem_ctx)
2816 {
2817         const char *p;
2818
2819         if (*pinfo2->comment == '\0') {
2820                 p = lp_comment(talloc_tos(), snum);
2821         } else {
2822                 p = pinfo2->comment;
2823         }
2824
2825         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2826 }
2827
2828 /*******************************************************************
2829  * fill a notify_info_data with the comment
2830  * location = "Room 1, floor 2, building 3"
2831  ********************************************************************/
2832
2833 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2834                                     int snum,
2835                                     struct spoolss_Notify *data,
2836                                     print_queue_struct *queue,
2837                                     struct spoolss_PrinterInfo2 *pinfo2,
2838                                     TALLOC_CTX *mem_ctx)
2839 {
2840         const char *loc = pinfo2->location;
2841         NTSTATUS status;
2842
2843         status = printer_list_get_printer(mem_ctx,
2844                                           pinfo2->sharename,
2845                                           NULL,
2846                                           &loc,
2847                                           NULL);
2848         if (NT_STATUS_IS_OK(status)) {
2849                 if (loc == NULL) {
2850                         loc = pinfo2->location;
2851                 }
2852         }
2853
2854         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2855 }
2856
2857 /*******************************************************************
2858  * fill a notify_info_data with the device mode
2859  * jfm:xxxx don't to it for know but that's a real problem !!!
2860  ********************************************************************/
2861
2862 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2863                                    int snum,
2864                                    struct spoolss_Notify *data,
2865                                    print_queue_struct *queue,
2866                                    struct spoolss_PrinterInfo2 *pinfo2,
2867                                    TALLOC_CTX *mem_ctx)
2868 {
2869         /* for a dummy implementation we have to zero the fields */
2870         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2871 }
2872
2873 /*******************************************************************
2874  * fill a notify_info_data with the separator file name
2875  ********************************************************************/
2876
2877 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2878                                    int snum,
2879                                    struct spoolss_Notify *data,
2880                                    print_queue_struct *queue,
2881                                    struct spoolss_PrinterInfo2 *pinfo2,
2882                                    TALLOC_CTX *mem_ctx)
2883 {
2884         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2885 }
2886
2887 /*******************************************************************
2888  * fill a notify_info_data with the print processor
2889  * jfm:xxxx return always winprint to indicate we don't do anything to it
2890  ********************************************************************/
2891
2892 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2893                                            int snum,
2894                                            struct spoolss_Notify *data,
2895                                            print_queue_struct *queue,
2896                                            struct spoolss_PrinterInfo2 *pinfo2,
2897                                            TALLOC_CTX *mem_ctx)
2898 {
2899         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2900 }
2901
2902 /*******************************************************************
2903  * fill a notify_info_data with the print processor options
2904  * jfm:xxxx send an empty string
2905  ********************************************************************/
2906
2907 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2908                                       int snum,
2909                                       struct spoolss_Notify *data,
2910                                       print_queue_struct *queue,
2911                                       struct spoolss_PrinterInfo2 *pinfo2,
2912                                       TALLOC_CTX *mem_ctx)
2913 {
2914         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2915 }
2916
2917 /*******************************************************************
2918  * fill a notify_info_data with the data type
2919  * jfm:xxxx always send RAW as data type
2920  ********************************************************************/
2921
2922 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2923                                     int snum,
2924                                     struct spoolss_Notify *data,
2925                                     print_queue_struct *queue,
2926                                     struct spoolss_PrinterInfo2 *pinfo2,
2927                                     TALLOC_CTX *mem_ctx)
2928 {
2929         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2930 }
2931
2932 /*******************************************************************
2933  * fill a notify_info_data with the security descriptor
2934  * jfm:xxxx send an null pointer to say no security desc
2935  * have to implement security before !
2936  ********************************************************************/
2937
2938 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2939                                          int snum,
2940                                          struct spoolss_Notify *data,
2941                                          print_queue_struct *queue,
2942                                          struct spoolss_PrinterInfo2 *pinfo2,
2943                                          TALLOC_CTX *mem_ctx)
2944 {
2945         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2946 }
2947
2948 /*******************************************************************
2949  * fill a notify_info_data with the attributes
2950  * jfm:xxxx a samba printer is always shared
2951  ********************************************************************/
2952
2953 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2954                                       int snum,
2955                                       struct spoolss_Notify *data,
2956                                       print_queue_struct *queue,
2957                                       struct spoolss_PrinterInfo2 *pinfo2,
2958                                       TALLOC_CTX *mem_ctx)
2959 {
2960         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2961 }
2962
2963 /*******************************************************************
2964  * fill a notify_info_data with the priority
2965  ********************************************************************/
2966
2967 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2968                                     int snum,
2969                                     struct spoolss_Notify *data,
2970                                     print_queue_struct *queue,
2971                                     struct spoolss_PrinterInfo2 *pinfo2,
2972                                     TALLOC_CTX *mem_ctx)
2973 {
2974         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2975 }
2976
2977 /*******************************************************************
2978  * fill a notify_info_data with the default priority
2979  ********************************************************************/
2980
2981 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2982                                             int snum,
2983                                             struct spoolss_Notify *data,
2984                                             print_queue_struct *queue,
2985                                             struct spoolss_PrinterInfo2 *pinfo2,
2986                                             TALLOC_CTX *mem_ctx)
2987 {
2988         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2989 }
2990
2991 /*******************************************************************
2992  * fill a notify_info_data with the start time
2993  ********************************************************************/
2994
2995 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2996                                       int snum,
2997                                       struct spoolss_Notify *data,
2998                                       print_queue_struct *queue,
2999                                       struct spoolss_PrinterInfo2 *pinfo2,
3000                                       TALLOC_CTX *mem_ctx)
3001 {
3002         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3003 }
3004
3005 /*******************************************************************
3006  * fill a notify_info_data with the until time
3007  ********************************************************************/
3008
3009 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3010                                       int snum,
3011                                       struct spoolss_Notify *data,
3012                                       print_queue_struct *queue,
3013                                       struct spoolss_PrinterInfo2 *pinfo2,
3014                                       TALLOC_CTX *mem_ctx)
3015 {
3016         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3017 }
3018
3019 /*******************************************************************
3020  * fill a notify_info_data with the status
3021  ********************************************************************/
3022
3023 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3024                                   int snum,
3025                                   struct spoolss_Notify *data,
3026                                   print_queue_struct *queue,
3027                                   struct spoolss_PrinterInfo2 *pinfo2,
3028                                   TALLOC_CTX *mem_ctx)
3029 {
3030         print_status_struct status;
3031
3032         print_queue_length(msg_ctx, snum, &status);
3033         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3034 }
3035
3036 /*******************************************************************
3037  * fill a notify_info_data with the number of jobs queued
3038  ********************************************************************/
3039
3040 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3041                                  int snum,
3042                                  struct spoolss_Notify *data,
3043                                  print_queue_struct *queue,
3044                                  struct spoolss_PrinterInfo2 *pinfo2,
3045                                  TALLOC_CTX *mem_ctx)
3046 {
3047         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3048                 data, print_queue_length(msg_ctx, snum, NULL));
3049 }
3050
3051 /*******************************************************************
3052  * fill a notify_info_data with the average ppm
3053  ********************************************************************/
3054
3055 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3056                                        int snum,
3057                                        struct spoolss_Notify *data,
3058                                        print_queue_struct *queue,
3059                                        struct spoolss_PrinterInfo2 *pinfo2,
3060                                        TALLOC_CTX *mem_ctx)
3061 {
3062         /* always respond 8 pages per minutes */
3063         /* a little hard ! */
3064         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3065 }
3066
3067 /*******************************************************************
3068  * fill a notify_info_data with username
3069  ********************************************************************/
3070
3071 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3072                                     int snum,
3073                                     struct spoolss_Notify *data,
3074                                     print_queue_struct *queue,
3075                                     struct spoolss_PrinterInfo2 *pinfo2,
3076                                     TALLOC_CTX *mem_ctx)
3077 {
3078         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3079 }
3080
3081 /*******************************************************************
3082  * fill a notify_info_data with job status
3083  ********************************************************************/
3084
3085 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3086                                       int snum,
3087                                       struct spoolss_Notify *data,
3088                                       print_queue_struct *queue,
3089                                       struct spoolss_PrinterInfo2 *pinfo2,
3090                                       TALLOC_CTX *mem_ctx)
3091 {
3092         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3093 }
3094
3095 /*******************************************************************
3096  * fill a notify_info_data with job name
3097  ********************************************************************/
3098
3099 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3100                                     int snum,
3101                                     struct spoolss_Notify *data,
3102                                     print_queue_struct *queue,
3103                                     struct spoolss_PrinterInfo2 *pinfo2,
3104                                     TALLOC_CTX *mem_ctx)
3105 {
3106         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3107 }
3108
3109 /*******************************************************************
3110  * fill a notify_info_data with job status
3111  ********************************************************************/
3112
3113 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3114                                              int snum,
3115                                              struct spoolss_Notify *data,
3116                                              print_queue_struct *queue,
3117                                              struct spoolss_PrinterInfo2 *pinfo2,
3118                                              TALLOC_CTX *mem_ctx)
3119 {
3120         /*
3121          * Now we're returning job status codes we just return a "" here. JRA.
3122          */
3123
3124         const char *p = "";
3125
3126 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3127         p = "unknown";
3128
3129         switch (queue->status) {
3130         case LPQ_QUEUED:
3131                 p = "Queued";
3132                 break;
3133         case LPQ_PAUSED:
3134                 p = "";    /* NT provides the paused string */
3135                 break;
3136         case LPQ_SPOOLING:
3137                 p = "Spooling";
3138                 break;
3139         case LPQ_PRINTING:
3140                 p = "Printing";
3141                 break;
3142         }
3143 #endif /* NO LONGER NEEDED. */
3144
3145         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3146 }
3147
3148 /*******************************************************************
3149  * fill a notify_info_data with job time
3150  ********************************************************************/
3151
3152 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3153                                     int snum,
3154                                     struct spoolss_Notify *data,
3155                                     print_queue_struct *queue,
3156                                     struct spoolss_PrinterInfo2 *pinfo2,
3157                                     TALLOC_CTX *mem_ctx)
3158 {
3159         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3160 }
3161
3162 /*******************************************************************
3163  * fill a notify_info_data with job size
3164  ********************************************************************/
3165
3166 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3167                                     int snum,
3168                                     struct spoolss_Notify *data,
3169                                     print_queue_struct *queue,
3170                                     struct spoolss_PrinterInfo2 *pinfo2,
3171                                     TALLOC_CTX *mem_ctx)
3172 {
3173         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3174 }
3175
3176 /*******************************************************************
3177  * fill a notify_info_data with page info
3178  ********************************************************************/
3179 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3180                                        int snum,
3181                                 struct spoolss_Notify *data,
3182                                 print_queue_struct *queue,
3183                                 struct spoolss_PrinterInfo2 *pinfo2,
3184                                 TALLOC_CTX *mem_ctx)
3185 {
3186         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3187 }
3188
3189 /*******************************************************************
3190  * fill a notify_info_data with pages printed info.
3191  ********************************************************************/
3192 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3193                                          int snum,
3194                                 struct spoolss_Notify *data,
3195                                 print_queue_struct *queue,
3196                                 struct spoolss_PrinterInfo2 *pinfo2,
3197                                 TALLOC_CTX *mem_ctx)
3198 {
3199         /* Add code when back-end tracks this */
3200         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3201 }
3202
3203 /*******************************************************************
3204  Fill a notify_info_data with job position.
3205  ********************************************************************/
3206
3207 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3208                                         int snum,
3209                                         struct spoolss_Notify *data,
3210                                         print_queue_struct *queue,
3211                                         struct spoolss_PrinterInfo2 *pinfo2,
3212                                         TALLOC_CTX *mem_ctx)
3213 {
3214         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3215 }
3216
3217 /*******************************************************************
3218  Fill a notify_info_data with submitted time.
3219  ********************************************************************/
3220
3221 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3222                                           int snum,
3223                                           struct spoolss_Notify *data,
3224                                           print_queue_struct *queue,
3225                                           struct spoolss_PrinterInfo2 *pinfo2,
3226                                           TALLOC_CTX *mem_ctx)
3227 {
3228         data->data.string.string = NULL;
3229         data->data.string.size = 0;
3230
3231         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3232                                &data->data.string.string,
3233                                &data->data.string.size);
3234
3235 }
3236
3237 struct s_notify_info_data_table
3238 {
3239         enum spoolss_NotifyType type;
3240         uint16_t field;
3241         const char *name;
3242         enum spoolss_NotifyTable variable_type;
3243         void (*fn) (struct messaging_context *msg_ctx,
3244                     int snum, struct spoolss_Notify *data,
3245                     print_queue_struct *queue,
3246                     struct spoolss_PrinterInfo2 *pinfo2,
3247                     TALLOC_CTX *mem_ctx);
3248 };
3249
3250 /* A table describing the various print notification constants and
3251    whether the notification data is a pointer to a variable sized
3252    buffer, a one value uint32_t or a two value uint32_t. */
3253
3254 static const struct s_notify_info_data_table notify_info_data_table[] =
3255 {
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3282 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3283 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3284 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3285 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3286 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3287 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3288 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3289 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3290 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3291 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3305 };
3306
3307 /*******************************************************************
3308  Return the variable_type of info_data structure.
3309 ********************************************************************/
3310
3311 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3312                                                                   uint16_t field)
3313 {
3314         int i=0;
3315
3316         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3317                 if ( (notify_info_data_table[i].type == type) &&
3318                      (notify_info_data_table[i].field == field) ) {
3319                         return notify_info_data_table[i].variable_type;
3320                 }
3321         }
3322
3323         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3324
3325         return (enum spoolss_NotifyTable) 0;
3326 }
3327
3328 /****************************************************************************
3329 ****************************************************************************/
3330
3331 static bool search_notify(enum spoolss_NotifyType type,
3332                           uint16_t field,
3333                           int *value)
3334 {
3335         int i;
3336
3337         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3338                 if (notify_info_data_table[i].type == type &&
3339                     notify_info_data_table[i].field == field &&
3340                     notify_info_data_table[i].fn != NULL) {
3341                         *value = i;
3342                         return true;
3343                 }
3344         }
3345
3346         return false;
3347 }
3348
3349 /****************************************************************************
3350 ****************************************************************************/
3351
3352 static void construct_info_data(struct spoolss_Notify *info_data,
3353                                 enum spoolss_NotifyType type,
3354                                 uint16_t field, int id)
3355 {
3356         info_data->type                 = type;
3357         info_data->field.field          = field;
3358         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3359         info_data->job_id               = id;
3360 }
3361
3362 /*******************************************************************
3363  *
3364  * fill a notify_info struct with info asked
3365  *
3366  ********************************************************************/
3367
3368 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3369                                           struct printer_handle *print_hnd,
3370                                           struct spoolss_NotifyInfo *info,
3371                                           struct spoolss_PrinterInfo2 *pinfo2,
3372                                           int snum,
3373                                           const struct spoolss_NotifyOptionType *option_type,
3374                                           uint32_t id,
3375                                           TALLOC_CTX *mem_ctx)
3376 {
3377         int field_num,j;
3378         enum spoolss_NotifyType type;
3379         uint16_t field;
3380
3381         struct spoolss_Notify *current_data;
3382
3383         type = option_type->type;
3384
3385         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3386                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3387                 option_type->count, lp_servicename(talloc_tos(), snum)));
3388
3389         for(field_num=0; field_num < option_type->count; field_num++) {
3390                 field = option_type->fields[field_num].field;
3391
3392                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3393
3394                 if (!search_notify(type, field, &j) )
3395                         continue;
3396
3397                 info->notifies = talloc_realloc(info, info->notifies,
3398                                                       struct spoolss_Notify,
3399                                                       info->count + 1);
3400                 if (info->notifies == NULL) {
3401                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3402                         return false;
3403                 }
3404
3405                 current_data = &info->notifies[info->count];
3406
3407                 construct_info_data(current_data, type, field, id);
3408
3409                 DEBUG(10, ("construct_notify_printer_info: "
3410                            "calling [%s]  snum=%d  printername=[%s])\n",
3411                            notify_info_data_table[j].name, snum,
3412                            pinfo2->printername));
3413
3414                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3415                                              NULL, pinfo2, mem_ctx);
3416
3417                 info->count++;
3418         }
3419
3420         return true;
3421 }
3422
3423 /*******************************************************************
3424  *
3425  * fill a notify_info struct with info asked
3426  *
3427  ********************************************************************/
3428
3429 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3430                                        print_queue_struct *queue,
3431                                        struct spoolss_NotifyInfo *info,
3432                                        struct spoolss_PrinterInfo2 *pinfo2,
3433                                        int snum,
3434                                        const struct spoolss_NotifyOptionType *option_type,
3435                                        uint32_t id,
3436                                        TALLOC_CTX *mem_ctx)
3437 {
3438         int field_num,j;
3439         enum spoolss_NotifyType type;
3440         uint16_t field;
3441         struct spoolss_Notify *current_data;
3442
3443         DEBUG(4,("construct_notify_jobs_info\n"));
3444
3445         type = option_type->type;
3446
3447         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3448                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3449                 option_type->count));
3450
3451         for(field_num=0; field_num<option_type->count; field_num++) {
3452                 field = option_type->fields[field_num].field;
3453
3454                 if (!search_notify(type, field, &j) )
3455                         continue;
3456
3457                 info->notifies = talloc_realloc(info, info->notifies,
3458                                                       struct spoolss_Notify,
3459                                                       info->count + 1);
3460                 if (info->notifies == NULL) {
3461                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3462                         return false;
3463                 }
3464
3465                 current_data=&(info->notifies[info->count]);
3466
3467                 construct_info_data(current_data, type, field, id);
3468                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3469                                              queue, pinfo2, mem_ctx);
3470                 info->count++;
3471         }
3472
3473         return true;
3474 }
3475
3476 /*
3477  * JFM: The enumeration is not that simple, it's even non obvious.
3478  *
3479  * let's take an example: I want to monitor the PRINTER SERVER for
3480  * the printer's name and the number of jobs currently queued.
3481  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3482  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3483  *
3484  * I have 3 printers on the back of my server.
3485  *
3486  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3487  * structures.
3488  *   Number     Data                    Id
3489  *      1       printer 1 name          1
3490  *      2       printer 1 cjob          1
3491  *      3       printer 2 name          2
3492  *      4       printer 2 cjob          2
3493  *      5       printer 3 name          3
3494  *      6       printer 3 name          3
3495  *
3496  * that's the print server case, the printer case is even worse.
3497  */
3498
3499 /*******************************************************************
3500  *
3501  * enumerate all printers on the printserver
3502  * fill a notify_info struct with info asked
3503  *
3504  ********************************************************************/
3505
3506 static WERROR printserver_notify_info(struct pipes_struct *p,
3507                                       struct policy_handle *hnd,
3508                                       struct spoolss_NotifyInfo *info,
3509                                       TALLOC_CTX *mem_ctx)
3510 {
3511         int snum;
3512         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3513         int n_services=lp_numservices();
3514         int i;
3515         struct spoolss_NotifyOption *option;
3516         struct spoolss_NotifyOptionType option_type;
3517         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3518         WERROR result;
3519
3520         DEBUG(4,("printserver_notify_info\n"));
3521
3522         if (!Printer)
3523                 return WERR_BADFID;
3524
3525         option = Printer->notify.option;
3526
3527         info->version   = 2;
3528         info->notifies  = NULL;
3529         info->count     = 0;
3530
3531         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3532            sending a ffpcn() request first */
3533
3534         if ( !option )
3535                 return WERR_BADFID;
3536
3537         for (i=0; i<option->count; i++) {
3538                 option_type = option->types[i];
3539
3540                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3541                         continue;
3542
3543                 for (snum = 0; snum < n_services; snum++) {
3544                         if (!lp_browseable(snum) ||
3545                             !lp_snum_ok(snum) ||
3546                             !lp_print_ok(snum)) {
3547                                 continue; /* skip */
3548                         }
3549
3550                         /* Maybe we should use the SYSTEM session_info here... */
3551                         result = winreg_get_printer_internal(mem_ctx,
3552                                                     get_session_info_system(),
3553                                                     p->msg_ctx,
3554                                                     lp_servicename(talloc_tos(), snum),
3555                                                     &pinfo2);
3556                         if (!W_ERROR_IS_OK(result)) {
3557                                 DEBUG(4, ("printserver_notify_info: "
3558                                           "Failed to get printer [%s]\n",
3559                                           lp_servicename(talloc_tos(), snum)));
3560                                 continue;
3561                         }
3562
3563
3564                         construct_notify_printer_info(p->msg_ctx,
3565                                                       Printer, info,
3566                                                       pinfo2, snum,
3567                                                       &option_type, snum,
3568                                                       mem_ctx);
3569
3570                         TALLOC_FREE(pinfo2);
3571                 }
3572         }
3573
3574 #if 0
3575         /*
3576          * Debugging information, don't delete.
3577          */
3578
3579         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3580         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3581         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3582
3583         for (i=0; i<info->count; i++) {
3584                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3585                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3586                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3587         }
3588 #endif
3589
3590         return WERR_OK;
3591 }
3592
3593 /*******************************************************************
3594  *
3595  * fill a notify_info struct with info asked
3596  *
3597  ********************************************************************/
3598
3599 static WERROR printer_notify_info(struct pipes_struct *p,
3600                                   struct policy_handle *hnd,
3601                                   struct spoolss_NotifyInfo *info,
3602                                   TALLOC_CTX *mem_ctx)
3603 {
3604         int snum;
3605         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3606         int i;
3607         uint32_t id;
3608         struct spoolss_NotifyOption *option;
3609         struct spoolss_NotifyOptionType option_type;
3610         int count,j;
3611         print_queue_struct *queue=NULL;
3612         print_status_struct status;
3613         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3614         WERROR result;
3615         struct tdb_print_db *pdb;
3616
3617         DEBUG(4,("printer_notify_info\n"));
3618
3619         if (!Printer)
3620                 return WERR_BADFID;
3621
3622         option = Printer->notify.option;
3623         id = 0x0;
3624
3625         info->version   = 2;
3626         info->notifies  = NULL;
3627         info->count     = 0;
3628
3629         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3630            sending a ffpcn() request first */
3631
3632         if ( !option )
3633                 return WERR_BADFID;
3634
3635         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3636                 return WERR_BADFID;
3637         }
3638
3639         pdb = get_print_db_byname(Printer->sharename);
3640         if (pdb == NULL) {
3641                 return WERR_BADFID;
3642         }
3643
3644         /* Maybe we should use the SYSTEM session_info here... */
3645         result = winreg_get_printer_internal(mem_ctx,
3646                                     get_session_info_system(),
3647                                     p->msg_ctx,
3648                                     lp_servicename(talloc_tos(), snum), &pinfo2);
3649         if (!W_ERROR_IS_OK(result)) {
3650                 result = WERR_BADFID;
3651                 goto err_pdb_drop;
3652         }
3653
3654         /*
3655          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3656          * correct servername.
3657          */
3658         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3659         if (pinfo2->servername == NULL) {
3660                 result = WERR_NOMEM;
3661                 goto err_pdb_drop;
3662         }
3663
3664         for (i = 0; i < option->count; i++) {
3665                 option_type = option->types[i];
3666
3667                 switch (option_type.type) {
3668                 case PRINTER_NOTIFY_TYPE:
3669                         if (construct_notify_printer_info(p->msg_ctx,
3670                                                           Printer, info,
3671                                                           pinfo2, snum,
3672                                                           &option_type, id,
3673                                                           mem_ctx)) {
3674                                 id--;
3675                         }
3676                         break;
3677
3678                 case JOB_NOTIFY_TYPE:
3679
3680                         count = print_queue_status(p->msg_ctx, snum, &queue,
3681                                                    &status);
3682
3683                         for (j = 0; j < count; j++) {
3684                                 uint32_t jobid;
3685                                 jobid = sysjob_to_jobid_pdb(pdb,
3686                                                             queue[j].sysjob);
3687                                 if (jobid == (uint32_t)-1) {
3688                                         DEBUG(2, ("ignoring untracked job %d\n",
3689                                                   queue[j].sysjob));
3690                                         continue;
3691                                 }
3692                                 /* FIXME check return value */
3693                                 construct_notify_jobs_info(p->msg_ctx,
3694                                                            &queue[j], info,
3695                                                            pinfo2, snum,
3696                                                            &option_type,
3697                                                            jobid,
3698                                                            mem_ctx);
3699                         }
3700
3701                         SAFE_FREE(queue);
3702                         break;
3703                 }
3704         }
3705
3706         /*
3707          * Debugging information, don't delete.
3708          */
3709         /*
3710         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3711         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3712         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3713
3714         for (i=0; i<info->count; i++) {
3715                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3716                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3717                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3718         }
3719         */
3720
3721         talloc_free(pinfo2);
3722         result = WERR_OK;
3723 err_pdb_drop:
3724         release_print_db(pdb);
3725         return result;
3726 }
3727
3728 /****************************************************************
3729  _spoolss_RouterRefreshPrinterChangeNotify
3730 ****************************************************************/
3731
3732 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3733                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3734 {
3735         struct spoolss_NotifyInfo *info;
3736
3737         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3738         WERROR result = WERR_BADFID;
3739
3740         /* we always have a spoolss_NotifyInfo struct */
3741         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3742         if (!info) {
3743                 result = WERR_NOMEM;
3744                 goto done;
3745         }
3746
3747         *r->out.info = info;
3748
3749         if (!Printer) {
3750                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3751                         "Invalid handle (%s:%u:%u).\n",
3752                         OUR_HANDLE(r->in.handle)));
3753                 goto done;
3754         }
3755
3756         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3757
3758         /*
3759          *      We are now using the change value, and
3760          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3761          *      I don't have a global notification system, I'm sending back all the
3762          *      information even when _NOTHING_ has changed.
3763          */
3764
3765         /* We need to keep track of the change value to send back in
3766            RRPCN replies otherwise our updates are ignored. */
3767
3768         Printer->notify.fnpcn = true;
3769
3770         if (Printer->notify.cli_chan != NULL &&
3771             Printer->notify.cli_chan->active_connections > 0) {
3772                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3773                         "Saving change value in request [%x]\n",
3774                         r->in.change_low));
3775                 Printer->notify.change = r->in.change_low;
3776         }
3777
3778         /* just ignore the spoolss_NotifyOption */
3779
3780         switch (Printer->printer_type) {
3781                 case SPLHND_SERVER:
3782                         result = printserver_notify_info(p, r->in.handle,
3783                                                          info, p->mem_ctx);
3784                         break;
3785
3786                 case SPLHND_PRINTER:
3787                         result = printer_notify_info(p, r->in.handle,
3788                                                      info, p->mem_ctx);
3789                         break;
3790         }
3791
3792         Printer->notify.fnpcn = false;
3793
3794 done:
3795         return result;
3796 }
3797
3798 /********************************************************************
3799  ********************************************************************/
3800
3801 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3802                                  const char *servername,
3803                                  const char *printername,
3804                                  const char **printername_p)
3805 {
3806         /* FIXME: add lp_force_printername() */
3807
3808         if (servername == NULL) {
3809                 *printername_p = talloc_strdup(mem_ctx, printername);
3810                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3811                 return WERR_OK;
3812         }
3813
3814         if (servername[0] == '\\' && servername[1] == '\\') {
3815                 servername += 2;
3816         }
3817
3818         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3819         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3820
3821         return WERR_OK;
3822 }
3823
3824 /********************************************************************
3825  ********************************************************************/
3826
3827 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3828                                           const char *printername)
3829 {
3830         if (dm == NULL) {
3831                 return;
3832         }
3833
3834         dm->devicename = talloc_strndup(dm, printername,
3835                                         MIN(strlen(printername), 31));
3836 }
3837
3838 /********************************************************************
3839  * construct_printer_info_0
3840  * fill a printer_info_0 struct
3841  ********************************************************************/
3842
3843 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3844                                       const struct auth_session_info *session_info,
3845                                       struct messaging_context *msg_ctx,
3846                                       struct spoolss_PrinterInfo2 *info2,
3847                                       const char *servername,
3848                                       struct spoolss_PrinterInfo0 *r,
3849                                       int snum)
3850 {
3851         int count;
3852         struct printer_session_counter *session_counter;
3853         struct timeval setuptime;
3854         print_status_struct status;
3855         WERROR result;
3856
3857         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3858         if (!W_ERROR_IS_OK(result)) {
3859                 return result;
3860         }
3861
3862         if (servername) {
3863                 r->servername = talloc_strdup(mem_ctx, servername);
3864                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3865         } else {
3866                 r->servername = NULL;
3867         }
3868
3869         count = print_queue_length(msg_ctx, snum, &status);
3870
3871         /* check if we already have a counter for this printer */
3872         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3873                 if (session_counter->snum == snum)
3874                         break;
3875         }
3876
3877         /* it's the first time, add it to the list */
3878         if (session_counter == NULL) {
3879                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3880                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3881                 session_counter->snum           = snum;
3882                 session_counter->counter        = 0;
3883                 DLIST_ADD(counter_list, session_counter);
3884         }
3885
3886         /* increment it */
3887         session_counter->counter++;
3888
3889         r->cjobs                        = count;
3890         r->total_jobs                   = 0;
3891         r->total_bytes                  = 0;
3892
3893         get_startup_time(&setuptime);
3894         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3895
3896         /* JFM:
3897          * the global_counter should be stored in a TDB as it's common to all the clients
3898          * and should be zeroed on samba startup
3899          */
3900         r->global_counter               = session_counter->counter;
3901         r->total_pages                  = 0;
3902         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3903         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3904         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3905         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3906         r->spooling                     = 0;
3907         r->max_spooling                 = 0;
3908         r->session_counter              = session_counter->counter;
3909         r->num_error_out_of_paper       = 0x0;
3910         r->num_error_not_ready          = 0x0;          /* number of print failure */
3911         r->job_error                    = 0x0;
3912         r->number_of_processors         = 0x1;
3913         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3914         r->high_part_total_bytes        = 0x0;
3915
3916         /* ChangeID in milliseconds*/
3917         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3918                                     info2->sharename, &r->change_id);
3919
3920         r->last_error                   = WERR_OK;
3921         r->status                       = nt_printq_status(status.status);
3922         r->enumerate_network_printers   = 0x0;
3923         r->c_setprinter                 = 0x0;
3924         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3925         r->processor_level              = 0x6;          /* 6  ???*/
3926         r->ref_ic                       = 0;
3927         r->reserved2                    = 0;
3928         r->reserved3                    = 0;
3929
3930         return WERR_OK;
3931 }
3932
3933
3934 /********************************************************************
3935  * construct_printer_info1
3936  * fill a spoolss_PrinterInfo1 struct
3937 ********************************************************************/
3938
3939 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3940                                       const struct spoolss_PrinterInfo2 *info2,
3941                                       uint32_t flags,
3942                                       const char *servername,
3943                                       struct spoolss_PrinterInfo1 *r,
3944                                       int snum)
3945 {
3946         WERROR result;
3947
3948         r->flags                = flags;
3949
3950         if (info2->comment == NULL || info2->comment[0] == '\0') {
3951                 r->comment      = lp_comment(mem_ctx, snum);
3952         } else {
3953                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3954         }
3955         W_ERROR_HAVE_NO_MEMORY(r->comment);
3956
3957         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3958         if (!W_ERROR_IS_OK(result)) {
3959                 return result;
3960         }
3961
3962         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3963                                                   r->name,
3964                                                   info2->drivername,
3965                                                   r->comment);
3966         W_ERROR_HAVE_NO_MEMORY(r->description);
3967
3968         return WERR_OK;
3969 }
3970
3971 /********************************************************************
3972  * construct_printer_info2
3973  * fill a spoolss_PrinterInfo2 struct
3974 ********************************************************************/
3975
3976 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3977                                       struct messaging_context *msg_ctx,
3978                                       const struct spoolss_PrinterInfo2 *info2,
3979                                       const char *servername,
3980                                       struct spoolss_PrinterInfo2 *r,
3981                                       int snum)
3982 {
3983         int count;
3984         print_status_struct status;
3985         WERROR result;
3986
3987         count = print_queue_length(msg_ctx, snum, &status);
3988
3989         if (servername) {
3990                 r->servername           = talloc_strdup(mem_ctx, servername);
3991                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3992         } else {
3993                 r->servername           = NULL;
3994         }
3995
3996         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3997         if (!W_ERROR_IS_OK(result)) {
3998                 return result;
3999         }
4000
4001         r->sharename            = lp_servicename(mem_ctx, snum);
4002         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4003         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4004         W_ERROR_HAVE_NO_MEMORY(r->portname);
4005         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4006         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4007
4008         if (info2->comment[0] == '\0') {
4009                 r->comment      = lp_comment(mem_ctx, snum);
4010         } else {
4011                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4012         }
4013         W_ERROR_HAVE_NO_MEMORY(r->comment);
4014
4015         r->location     = talloc_strdup(mem_ctx, info2->location);
4016         if (info2->location[0] == '\0') {
4017                 const char *loc = NULL;
4018                 NTSTATUS nt_status;
4019
4020                 nt_status = printer_list_get_printer(mem_ctx,
4021                                                      info2->sharename,
4022                                                      NULL,
4023                                                      &loc,
4024                                                      NULL);
4025                 if (NT_STATUS_IS_OK(nt_status)) {
4026                         if (loc != NULL) {
4027                                 r->location = talloc_strdup(mem_ctx, loc);
4028                         }
4029                 }
4030         }
4031         W_ERROR_HAVE_NO_MEMORY(r->location);
4032
4033         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4034         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4035         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4036         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4037         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4038         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4039         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4040         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4041
4042         r->attributes           = info2->attributes;
4043
4044         r->priority             = info2->priority;
4045         r->defaultpriority      = info2->defaultpriority;
4046         r->starttime            = info2->starttime;
4047         r->untiltime            = info2->untiltime;
4048         r->status               = nt_printq_status(status.status);
4049         r->cjobs                = count;
4050         r->averageppm           = info2->averageppm;
4051
4052         if (info2->devmode != NULL) {
4053                 result = copy_devicemode(mem_ctx,
4054                                          info2->devmode,
4055                                          &r->devmode);
4056                 if (!W_ERROR_IS_OK(result)) {
4057                         return result;
4058                 }
4059         } else if (lp_default_devmode(snum)) {
4060                 result = spoolss_create_default_devmode(mem_ctx,
4061                                                         info2->printername,
4062                                                         &r->devmode);
4063                 if (!W_ERROR_IS_OK(result)) {
4064                         return result;
4065                 }
4066         } else {
4067                 r->devmode = NULL;
4068                 DEBUG(8,("Returning NULL Devicemode!\n"));
4069         }
4070
4071         compose_devicemode_devicename(r->devmode, r->printername);
4072
4073         r->secdesc = NULL;
4074
4075         if (info2->secdesc != NULL) {
4076                 /* don't use talloc_steal() here unless you do a deep steal of all
4077                    the SEC_DESC members */
4078
4079                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4080         }
4081
4082         return WERR_OK;
4083 }
4084
4085 /********************************************************************
4086  * construct_printer_info3
4087  * fill a spoolss_PrinterInfo3 struct
4088  ********************************************************************/
4089
4090 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4091                                       const struct spoolss_PrinterInfo2 *info2,
4092                                       const char *servername,
4093                                       struct spoolss_PrinterInfo3 *r,
4094                                       int snum)
4095 {
4096         /* These are the components of the SD we are returning. */
4097
4098         if (info2->secdesc != NULL) {
4099                 /* don't use talloc_steal() here unless you do a deep steal of all
4100                    the SEC_DESC members */
4101
4102                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4103                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4104         }
4105
4106         return WERR_OK;
4107 }
4108
4109 /********************************************************************
4110  * construct_printer_info4
4111  * fill a spoolss_PrinterInfo4 struct
4112  ********************************************************************/
4113
4114 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4115                                       const struct spoolss_PrinterInfo2 *info2,
4116                                       const char *servername,
4117                                       struct spoolss_PrinterInfo4 *r,
4118                                       int snum)
4119 {
4120         WERROR result;
4121
4122         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4123         if (!W_ERROR_IS_OK(result)) {
4124                 return result;
4125         }
4126
4127         if (servername) {
4128                 r->servername   = talloc_strdup(mem_ctx, servername);
4129                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4130         } else {
4131                 r->servername = NULL;
4132         }
4133
4134         r->attributes   = info2->attributes;
4135
4136         return WERR_OK;
4137 }
4138
4139 /********************************************************************
4140  * construct_printer_info5
4141  * fill a spoolss_PrinterInfo5 struct
4142  ********************************************************************/
4143
4144 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4145                                       const struct spoolss_PrinterInfo2 *info2,
4146                                       const char *servername,
4147                                       struct spoolss_PrinterInfo5 *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         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4158         W_ERROR_HAVE_NO_MEMORY(r->portname);
4159
4160         r->attributes   = info2->attributes;
4161
4162         /* these two are not used by NT+ according to MSDN */
4163         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4164         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4165
4166         return WERR_OK;
4167 }
4168
4169 /********************************************************************
4170  * construct_printer_info_6
4171  * fill a spoolss_PrinterInfo6 struct
4172  ********************************************************************/
4173
4174 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4175                                       struct messaging_context *msg_ctx,
4176                                       const struct spoolss_PrinterInfo2 *info2,
4177                                       const char *servername,
4178                                       struct spoolss_PrinterInfo6 *r,
4179                                       int snum)
4180 {
4181         print_status_struct status;
4182
4183         print_queue_length(msg_ctx, snum, &status);
4184
4185         r->status = nt_printq_status(status.status);
4186
4187         return WERR_OK;
4188 }
4189
4190 /********************************************************************
4191  * construct_printer_info7
4192  * fill a spoolss_PrinterInfo7 struct
4193  ********************************************************************/
4194
4195 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4196                                       struct messaging_context *msg_ctx,
4197                                       const char *servername,
4198                                       struct spoolss_PrinterInfo7 *r,
4199                                       int snum)
4200 {
4201         const struct auth_session_info *session_info;
4202         char *printer;
4203         WERROR werr;
4204         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4205         if (tmp_ctx == NULL) {
4206                 return WERR_NOMEM;
4207         }
4208
4209         session_info = get_session_info_system();
4210         SMB_ASSERT(session_info != NULL);
4211
4212         printer = lp_servicename(tmp_ctx, snum);
4213         if (printer == NULL) {
4214                 DEBUG(0, ("invalid printer snum %d\n", snum));
4215                 werr = WERR_INVALID_PARAM;
4216                 goto out_tmp_free;
4217         }
4218
4219         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4220                                  servername, printer, NULL)) {
4221                 struct GUID guid;
4222                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4223                                            printer, &guid);
4224                 if (!W_ERROR_IS_OK(werr)) {
4225                         goto out_tmp_free;
4226                 }
4227                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4228                 r->action = DSPRINT_PUBLISH;
4229         } else {
4230                 r->guid = talloc_strdup(mem_ctx, "");
4231                 r->action = DSPRINT_UNPUBLISH;
4232         }
4233         if (r->guid == NULL) {
4234                 werr = WERR_NOMEM;
4235                 goto out_tmp_free;
4236         }
4237
4238         werr = WERR_OK;
4239 out_tmp_free:
4240         talloc_free(tmp_ctx);
4241         return werr;
4242 }
4243
4244 /********************************************************************
4245  * construct_printer_info8
4246  * fill a spoolss_PrinterInfo8 struct
4247  ********************************************************************/
4248
4249 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4250                                       const struct spoolss_PrinterInfo2 *info2,
4251                                       const char *servername,
4252                                       struct spoolss_DeviceModeInfo *r,
4253                                       int snum)
4254 {
4255         WERROR result;
4256         const char *printername;
4257
4258         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4259         if (!W_ERROR_IS_OK(result)) {
4260                 return result;
4261         }
4262
4263         if (info2->devmode != NULL) {
4264                 result = copy_devicemode(mem_ctx,
4265                                          info2->devmode,
4266                                          &r->devmode);
4267                 if (!W_ERROR_IS_OK(result)) {
4268                         return result;
4269                 }
4270         } else if (lp_default_devmode(snum)) {
4271                 result = spoolss_create_default_devmode(mem_ctx,
4272                                                         info2->printername,
4273                                                         &r->devmode);
4274                 if (!W_ERROR_IS_OK(result)) {
4275                         return result;
4276                 }
4277         } else {
4278                 r->devmode = NULL;
4279                 DEBUG(8,("Returning NULL Devicemode!\n"));
4280         }
4281
4282         compose_devicemode_devicename(r->devmode, printername);
4283
4284         return WERR_OK;
4285 }
4286
4287 /********************************************************************
4288  Spoolss_enumprinters.
4289 ********************************************************************/
4290
4291 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4292                                            const struct auth_session_info *session_info,
4293                                            struct messaging_context *msg_ctx,
4294                                            const char *servername,
4295                                            uint32_t level,
4296                                            uint32_t flags,
4297                                            union spoolss_PrinterInfo **info_p,
4298                                            uint32_t *count_p)
4299 {
4300         int snum;
4301         int n_services;
4302         union spoolss_PrinterInfo *info = NULL;
4303         uint32_t count = 0;
4304         WERROR result = WERR_OK;
4305         struct dcerpc_binding_handle *b = NULL;
4306         TALLOC_CTX *tmp_ctx = NULL;
4307
4308         tmp_ctx = talloc_new(mem_ctx);
4309         if (!tmp_ctx) {
4310                 return WERR_NOMEM;
4311         }
4312
4313         /*
4314          * printer shares are updated on client enumeration. The background
4315          * printer process updates printer_list.tdb at regular intervals.
4316          */
4317         become_root();
4318         delete_and_reload_printers(server_event_context(), msg_ctx);
4319         unbecome_root();
4320
4321         n_services = lp_numservices();
4322         *count_p = 0;
4323         *info_p = NULL;
4324
4325         for (snum = 0; snum < n_services; snum++) {
4326
4327                 const char *printer;
4328                 struct spoolss_PrinterInfo2 *info2;
4329
4330                 if (!snum_is_shared_printer(snum)) {
4331                         continue;
4332                 }
4333
4334                 printer = lp_const_servicename(snum);
4335
4336                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4337                         printer, snum));
4338
4339                 if (b == NULL) {
4340                         result = winreg_printer_binding_handle(tmp_ctx,
4341                                                                session_info,
4342                                                                msg_ctx,
4343                                                                &b);
4344                         if (!W_ERROR_IS_OK(result)) {
4345                                 goto out;
4346                         }
4347                 }
4348
4349                 result = winreg_create_printer(tmp_ctx, b,
4350                                                printer);
4351                 if (!W_ERROR_IS_OK(result)) {
4352                         goto out;
4353                 }
4354
4355                 info = talloc_realloc(tmp_ctx, info,
4356                                             union spoolss_PrinterInfo,
4357                                             count + 1);
4358                 if (!info) {
4359                         result = WERR_NOMEM;
4360                         goto out;
4361                 }
4362
4363                 result = winreg_get_printer(tmp_ctx, b,
4364                                             printer, &info2);
4365                 if (!W_ERROR_IS_OK(result)) {
4366                         goto out;
4367                 }
4368
4369                 switch (level) {
4370                 case 0:
4371                         result = construct_printer_info0(info, session_info,
4372                                                          msg_ctx, info2,
4373                                                          servername,
4374                                                          &info[count].info0, snum);
4375                         break;
4376                 case 1:
4377                         result = construct_printer_info1(info, info2, flags,
4378                                                          servername,
4379                                                          &info[count].info1, snum);
4380                         break;
4381                 case 2:
4382                         result = construct_printer_info2(info, msg_ctx, info2,
4383                                                          servername,
4384                                                          &info[count].info2, snum);
4385                         break;
4386                 case 4:
4387                         result = construct_printer_info4(info, info2,
4388                                                          servername,
4389                                                          &info[count].info4, snum);
4390                         break;
4391                 case 5:
4392                         result = construct_printer_info5(info, info2,
4393                                                          servername,
4394                                                          &info[count].info5, snum);
4395                         break;
4396
4397                 default:
4398                         result = WERR_UNKNOWN_LEVEL;
4399                         goto out;
4400                 }
4401
4402                 if (!W_ERROR_IS_OK(result)) {
4403                         goto out;
4404                 }
4405
4406                 count++;
4407         }
4408
4409 out:
4410         if (W_ERROR_IS_OK(result)) {
4411                 *info_p = talloc_move(mem_ctx, &info);
4412                 *count_p = count;
4413         }
4414
4415         talloc_free(tmp_ctx);
4416
4417         return result;
4418 }
4419
4420 /********************************************************************
4421  * handle enumeration of printers at level 0
4422  ********************************************************************/
4423
4424 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4425                                   const struct auth_session_info *session_info,
4426                                   struct messaging_context *msg_ctx,
4427                                   uint32_t flags,
4428                                   const char *servername,
4429                                   union spoolss_PrinterInfo **info,
4430                                   uint32_t *count)
4431 {
4432         DEBUG(4,("enum_all_printers_info_0\n"));
4433
4434         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4435                                             servername, 0, flags, info, count);
4436 }
4437
4438
4439 /********************************************************************
4440 ********************************************************************/
4441
4442 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4443                                        const struct auth_session_info *session_info,
4444                                        struct messaging_context *msg_ctx,
4445                                        const char *servername,
4446                                        uint32_t flags,
4447                                        union spoolss_PrinterInfo **info,
4448                                        uint32_t *count)
4449 {
4450         DEBUG(4,("enum_all_printers_info_1\n"));
4451
4452         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4453                                             servername, 1, flags, info, count);
4454 }
4455
4456 /********************************************************************
4457  enum_all_printers_info_1_local.
4458 *********************************************************************/
4459
4460 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4461                                              const struct auth_session_info *session_info,
4462                                              struct messaging_context *msg_ctx,
4463                                              const char *servername,
4464                                              union spoolss_PrinterInfo **info,
4465                                              uint32_t *count)
4466 {
4467         DEBUG(4,("enum_all_printers_info_1_local\n"));
4468
4469         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4470                                         servername, PRINTER_ENUM_ICON8, info, count);
4471 }
4472
4473 /********************************************************************
4474  enum_all_printers_info_1_name.
4475 *********************************************************************/
4476
4477 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4478                                             const struct auth_session_info *session_info,
4479                                             struct messaging_context *msg_ctx,
4480                                             const char *servername,
4481                                             union spoolss_PrinterInfo **info,
4482                                             uint32_t *count)
4483 {
4484         const char *s = servername;
4485
4486         DEBUG(4,("enum_all_printers_info_1_name\n"));
4487
4488         if (servername != NULL &&
4489             (servername[0] == '\\') && (servername[1] == '\\')) {
4490                 s = servername + 2;
4491         }
4492
4493         if (!is_myname_or_ipaddr(s)) {
4494                 return WERR_INVALID_NAME;
4495         }
4496
4497         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4498                                         servername, PRINTER_ENUM_ICON8, info, count);
4499 }
4500
4501 /********************************************************************
4502  enum_all_printers_info_1_network.
4503 *********************************************************************/
4504
4505 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4506                                                const struct auth_session_info *session_info,
4507                                                struct messaging_context *msg_ctx,
4508                                                const char *servername,
4509                                                union spoolss_PrinterInfo **info,
4510                                                uint32_t *count)
4511 {
4512         const char *s = servername;
4513
4514         DEBUG(4,("enum_all_printers_info_1_network\n"));
4515
4516         /* If we respond to a enum_printers level 1 on our name with flags
4517            set to PRINTER_ENUM_REMOTE with a list of printers then these
4518            printers incorrectly appear in the APW browse list.
4519            Specifically the printers for the server appear at the workgroup
4520            level where all the other servers in the domain are
4521            listed. Windows responds to this call with a
4522            WERR_CAN_NOT_COMPLETE so we should do the same. */
4523
4524         if (servername != NULL &&
4525             (servername[0] == '\\') && (servername[1] == '\\')) {
4526                  s = servername + 2;
4527         }
4528
4529         if (is_myname_or_ipaddr(s)) {
4530                  return WERR_CAN_NOT_COMPLETE;
4531         }
4532
4533         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4534                                         servername, PRINTER_ENUM_NAME, info, count);
4535 }
4536
4537 /********************************************************************
4538  * api_spoolss_enumprinters
4539  *
4540  * called from api_spoolss_enumprinters (see this to understand)
4541  ********************************************************************/
4542
4543 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4544                                        const struct auth_session_info *session_info,
4545                                        struct messaging_context *msg_ctx,
4546                                        const char *servername,
4547                                        union spoolss_PrinterInfo **info,
4548                                        uint32_t *count)
4549 {
4550         DEBUG(4,("enum_all_printers_info_2\n"));
4551
4552         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4553                                             servername, 2, 0, info, count);
4554 }
4555
4556 /********************************************************************
4557  * handle enumeration of printers at level 1
4558  ********************************************************************/
4559
4560 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4561                                   const struct auth_session_info *session_info,
4562                                   struct messaging_context *msg_ctx,
4563                                   uint32_t flags,
4564                                   const char *servername,
4565                                   union spoolss_PrinterInfo **info,
4566                                   uint32_t *count)
4567 {
4568         /* Not all the flags are equals */
4569
4570         if (flags & PRINTER_ENUM_LOCAL) {
4571                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4572                                                       msg_ctx, servername, info, count);
4573         }
4574
4575         if (flags & PRINTER_ENUM_NAME) {
4576                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4577                                                      msg_ctx, servername, info,
4578                                                      count);
4579         }
4580
4581         if (flags & PRINTER_ENUM_NETWORK) {
4582                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4583                                                         msg_ctx, servername, info,
4584                                                         count);
4585         }
4586
4587         return WERR_OK; /* NT4sp5 does that */
4588 }
4589
4590 /********************************************************************
4591  * handle enumeration of printers at level 2
4592  ********************************************************************/
4593
4594 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4595                                   const struct auth_session_info *session_info,
4596                                   struct messaging_context *msg_ctx,
4597                                   uint32_t flags,
4598                                   const char *servername,
4599                                   union spoolss_PrinterInfo **info,
4600                                   uint32_t *count)
4601 {
4602         if (flags & PRINTER_ENUM_LOCAL) {
4603
4604                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4605                                                 servername,
4606                                                 info, count);
4607         }
4608
4609         if (flags & PRINTER_ENUM_NAME) {
4610                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4611                         return WERR_INVALID_NAME;
4612                 }
4613
4614                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4615                                                 servername,
4616                                                 info, count);
4617         }
4618
4619         if (flags & PRINTER_ENUM_REMOTE) {
4620                 return WERR_UNKNOWN_LEVEL;
4621         }
4622
4623         return WERR_OK;
4624 }
4625
4626 /********************************************************************
4627  * handle enumeration of printers at level 4
4628  ********************************************************************/
4629
4630 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4631                                   const struct auth_session_info *session_info,
4632                                   struct messaging_context *msg_ctx,
4633                                   uint32_t flags,
4634                                   const char *servername,
4635                                   union spoolss_PrinterInfo **info,
4636                                   uint32_t *count)
4637 {
4638         DEBUG(4,("enum_all_printers_info_4\n"));
4639
4640         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4641                                             servername, 4, flags, info, count);
4642 }
4643
4644
4645 /********************************************************************
4646  * handle enumeration of printers at level 5
4647  ********************************************************************/
4648
4649 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4650                                   const struct auth_session_info *session_info,
4651                                   struct messaging_context *msg_ctx,
4652                                   uint32_t flags,
4653                                   const char *servername,
4654                                   union spoolss_PrinterInfo **info,
4655                                   uint32_t *count)
4656 {
4657         DEBUG(4,("enum_all_printers_info_5\n"));
4658
4659         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4660                                             servername, 5, flags, info, count);
4661 }
4662
4663 /****************************************************************
4664  _spoolss_EnumPrinters
4665 ****************************************************************/
4666
4667 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4668                              struct spoolss_EnumPrinters *r)
4669 {
4670         const struct auth_session_info *session_info = get_session_info_system();
4671         WERROR result;
4672
4673         /* that's an [in out] buffer */
4674
4675         if (!r->in.buffer && (r->in.offered != 0)) {
4676                 return WERR_INVALID_PARAM;
4677         }
4678
4679         DEBUG(4,("_spoolss_EnumPrinters\n"));
4680
4681         *r->out.needed = 0;
4682         *r->out.count = 0;
4683         *r->out.info = NULL;
4684
4685         /*
4686          * Level 1:
4687          *          flags==PRINTER_ENUM_NAME
4688          *           if name=="" then enumerates all printers
4689          *           if name!="" then enumerate the printer
4690          *          flags==PRINTER_ENUM_REMOTE
4691          *          name is NULL, enumerate printers
4692          * Level 2: name!="" enumerates printers, name can't be NULL
4693          * Level 3: doesn't exist
4694          * Level 4: does a local registry lookup
4695          * Level 5: same as Level 2
4696          */
4697
4698         if (r->in.server && r->in.server[0] == '\0') {
4699                 r->in.server = NULL;
4700         }
4701
4702         switch (r->in.level) {
4703         case 0:
4704                 result = enumprinters_level0(p->mem_ctx, session_info,
4705                                              p->msg_ctx, r->in.flags,
4706                                              r->in.server,
4707                                              r->out.info, r->out.count);
4708                 break;
4709         case 1:
4710                 result = enumprinters_level1(p->mem_ctx, session_info,
4711                                              p->msg_ctx, r->in.flags,
4712                                              r->in.server,
4713                                              r->out.info, r->out.count);
4714                 break;
4715         case 2:
4716                 result = enumprinters_level2(p->mem_ctx, session_info,
4717                                              p->msg_ctx, r->in.flags,
4718                                              r->in.server,
4719                                              r->out.info, r->out.count);
4720                 break;
4721         case 4:
4722                 result = enumprinters_level4(p->mem_ctx, session_info,
4723                                              p->msg_ctx, r->in.flags,
4724                                              r->in.server,
4725                                              r->out.info, r->out.count);
4726                 break;
4727         case 5:
4728                 result = enumprinters_level5(p->mem_ctx, session_info,
4729                                              p->msg_ctx, r->in.flags,
4730                                              r->in.server,
4731                                              r->out.info, r->out.count);
4732                 break;
4733         default:
4734                 return WERR_UNKNOWN_LEVEL;
4735         }
4736
4737         if (!W_ERROR_IS_OK(result)) {
4738                 return result;
4739         }
4740
4741         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4742                                                      spoolss_EnumPrinters,
4743                                                      *r->out.info, r->in.level,
4744                                                      *r->out.count);
4745         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4746         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4747
4748         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4749 }
4750
4751 /****************************************************************
4752  _spoolss_GetPrinter
4753 ****************************************************************/
4754
4755 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4756                            struct spoolss_GetPrinter *r)
4757 {
4758         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4759         struct spoolss_PrinterInfo2 *info2 = NULL;
4760         WERROR result = WERR_OK;
4761         int snum;
4762
4763         /* that's an [in out] buffer */
4764
4765         if (!r->in.buffer && (r->in.offered != 0)) {
4766                 return WERR_INVALID_PARAM;
4767         }
4768
4769         *r->out.needed = 0;
4770
4771         if (Printer == NULL) {
4772                 return WERR_BADFID;
4773         }
4774
4775         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4776                 return WERR_BADFID;
4777         }
4778
4779         result = winreg_get_printer_internal(p->mem_ctx,
4780                                     get_session_info_system(),
4781                                     p->msg_ctx,
4782                                     lp_const_servicename(snum),
4783                                     &info2);
4784         if (!W_ERROR_IS_OK(result)) {
4785                 goto out;
4786         }
4787
4788         switch (r->in.level) {
4789         case 0:
4790                 result = construct_printer_info0(p->mem_ctx,
4791                                                  get_session_info_system(),
4792                                                  p->msg_ctx,
4793                                                  info2,
4794                                                  Printer->servername,
4795                                                  &r->out.info->info0,
4796                                                  snum);
4797                 break;
4798         case 1:
4799                 result = construct_printer_info1(p->mem_ctx, info2,
4800                                                  PRINTER_ENUM_ICON8,
4801                                                  Printer->servername,
4802                                                  &r->out.info->info1, snum);
4803                 break;
4804         case 2:
4805                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4806                                                  Printer->servername,
4807                                                  &r->out.info->info2, snum);
4808                 break;
4809         case 3:
4810                 result = construct_printer_info3(p->mem_ctx, info2,
4811                                                  Printer->servername,
4812                                                  &r->out.info->info3, snum);
4813                 break;
4814         case 4:
4815                 result = construct_printer_info4(p->mem_ctx, info2,
4816                                                  Printer->servername,
4817                                                  &r->out.info->info4, snum);
4818                 break;
4819         case 5:
4820                 result = construct_printer_info5(p->mem_ctx, info2,
4821                                                  Printer->servername,
4822                                                  &r->out.info->info5, snum);
4823                 break;
4824         case 6:
4825                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4826                                                  Printer->servername,
4827                                                  &r->out.info->info6, snum);
4828                 break;
4829         case 7:
4830                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4831                                                  Printer->servername,
4832                                                  &r->out.info->info7, snum);
4833                 break;
4834         case 8:
4835                 result = construct_printer_info8(p->mem_ctx, info2,
4836                                                  Printer->servername,
4837                                                  &r->out.info->info8, snum);
4838                 break;
4839         default:
4840                 result = WERR_UNKNOWN_LEVEL;
4841                 break;
4842         }
4843         TALLOC_FREE(info2);
4844
4845  out:
4846         if (!W_ERROR_IS_OK(result)) {
4847                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4848                           r->in.level, win_errstr(result)));
4849                 TALLOC_FREE(r->out.info);
4850                 return result;
4851         }
4852
4853         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4854                                                r->out.info, r->in.level);
4855         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4856
4857         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4858 }
4859
4860 /********************************************************************
4861  ********************************************************************/
4862
4863 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4864         do { \
4865                 if (in && strlen(in)) { \
4866                         out = talloc_strdup(mem_ctx, in); \
4867                 } else { \
4868                         out = talloc_strdup(mem_ctx, ""); \
4869                 } \
4870                 W_ERROR_HAVE_NO_MEMORY(out); \
4871         } while (0);
4872
4873 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4874         do { \
4875                 if (in && strlen(in)) { \
4876                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4877                 } else { \
4878                         out = talloc_strdup(mem_ctx, ""); \
4879                 } \
4880                 W_ERROR_HAVE_NO_MEMORY(out); \
4881         } while (0);
4882
4883 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4884                                                   const char **string_array,
4885                                                   const char ***presult,
4886                                                   const char *cservername,
4887                                                   const char *arch,
4888                                                   int version)
4889 {
4890         int i, num_strings = 0;
4891         const char **array = NULL;
4892
4893         if (string_array == NULL) {
4894                 return WERR_INVALID_PARAMETER;
4895         }
4896
4897         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4898                 const char *str = NULL;
4899
4900                 if (cservername == NULL || arch == NULL) {
4901                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4902                 } else {
4903                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4904                 }
4905
4906                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4907                         TALLOC_FREE(array);
4908                         return WERR_NOMEM;
4909                 }
4910         }
4911
4912         if (i > 0) {
4913                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4914                              &array, &num_strings);
4915         }
4916
4917         if (presult != NULL) {
4918                 *presult = array;
4919         } else {
4920                 talloc_free(array);
4921         }
4922
4923         return WERR_OK;
4924 }
4925
4926 /********************************************************************
4927  * fill a spoolss_DriverInfo1 struct
4928  ********************************************************************/
4929
4930 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4931                                         struct spoolss_DriverInfo1 *r,
4932                                         const struct spoolss_DriverInfo8 *driver,
4933                                         const char *servername)
4934 {
4935         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4936         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4937
4938         return WERR_OK;
4939 }
4940
4941 /********************************************************************
4942  * fill a spoolss_DriverInfo2 struct
4943  ********************************************************************/
4944
4945 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4946                                         struct spoolss_DriverInfo2 *r,
4947                                         const struct spoolss_DriverInfo8 *driver,
4948                                         const char *servername)
4949
4950 {
4951         const char *cservername = canon_servername(servername);
4952
4953         r->version              = driver->version;
4954
4955         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4956         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4957         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4958         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4959
4960         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4961                                driver->architecture,
4962                                driver->version,
4963                                driver->driver_path,
4964                                r->driver_path);
4965
4966         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4967                                driver->architecture,
4968                                driver->version,
4969                                driver->data_file,
4970                                r->data_file);
4971
4972         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4973                                driver->architecture,
4974                                driver->version,
4975                                driver->config_file,
4976                                r->config_file);
4977
4978         return WERR_OK;
4979 }
4980
4981 /********************************************************************
4982  * fill a spoolss_DriverInfo3 struct
4983  ********************************************************************/
4984
4985 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4986                                         struct spoolss_DriverInfo3 *r,
4987                                         const struct spoolss_DriverInfo8 *driver,
4988                                         const char *servername)
4989 {
4990         const char *cservername = canon_servername(servername);
4991
4992         r->version              = driver->version;
4993
4994         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4995         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4996         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4997         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4998
4999         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5000                                driver->architecture,
5001                                driver->version,
5002                                driver->driver_path,
5003                                r->driver_path);
5004
5005         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5006                                driver->architecture,
5007                                driver->version,
5008                                driver->data_file,
5009                                r->data_file);
5010
5011         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5012                                driver->architecture,
5013                                driver->version,
5014                                driver->config_file,
5015                                r->config_file);
5016
5017         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5018                                driver->architecture,
5019                                driver->version,
5020                                driver->help_file,
5021                                r->help_file);
5022
5023         FILL_DRIVER_STRING(mem_ctx,
5024                            driver->monitor_name,
5025                            r->monitor_name);
5026
5027         FILL_DRIVER_STRING(mem_ctx,
5028                            driver->default_datatype,
5029                            r->default_datatype);
5030
5031         return string_array_from_driver_info(mem_ctx,
5032                                              driver->dependent_files,
5033                                              &r->dependent_files,
5034                                              cservername,
5035                                              driver->architecture,
5036                                              driver->version);
5037 }
5038
5039 /********************************************************************
5040  * fill a spoolss_DriverInfo4 struct
5041  ********************************************************************/
5042
5043 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5044                                         struct spoolss_DriverInfo4 *r,
5045                                         const struct spoolss_DriverInfo8 *driver,
5046                                         const char *servername)
5047 {
5048         const char *cservername = canon_servername(servername);
5049         WERROR result;
5050
5051         r->version              = driver->version;
5052
5053         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5054         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5055         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5056         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5057
5058         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5059                                driver->architecture,
5060                                driver->version,
5061                                driver->driver_path,
5062                                r->driver_path);
5063
5064         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5065                                driver->architecture,
5066                                driver->version,
5067                                driver->data_file,
5068                                r->data_file);
5069
5070         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5071                                driver->architecture,
5072                                driver->version,
5073                                driver->config_file,
5074                                r->config_file);
5075
5076         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5077                                driver->architecture,
5078                                driver->version,
5079                                driver->help_file,
5080                                r->help_file);
5081
5082         result = string_array_from_driver_info(mem_ctx,
5083                                                driver->dependent_files,
5084                                                &r->dependent_files,
5085                                                cservername,
5086                                                driver->architecture,
5087                                                driver->version);
5088         if (!W_ERROR_IS_OK(result)) {
5089                 return result;
5090         }
5091
5092         FILL_DRIVER_STRING(mem_ctx,
5093                            driver->monitor_name,
5094                            r->monitor_name);
5095
5096         FILL_DRIVER_STRING(mem_ctx,
5097                            driver->default_datatype,
5098                            r->default_datatype);
5099
5100
5101         result = string_array_from_driver_info(mem_ctx,
5102                                                driver->previous_names,
5103                                                &r->previous_names,
5104                                                NULL, NULL, 0);
5105
5106         return result;
5107 }
5108
5109 /********************************************************************
5110  * fill a spoolss_DriverInfo5 struct
5111  ********************************************************************/
5112
5113 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5114                                         struct spoolss_DriverInfo5 *r,
5115                                         const struct spoolss_DriverInfo8 *driver,
5116                                         const char *servername)
5117 {
5118         const char *cservername = canon_servername(servername);
5119
5120         r->version              = driver->version;
5121
5122         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5123         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5124         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5125         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5126
5127         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5128                                driver->architecture,
5129                                driver->version,
5130                                driver->driver_path,
5131                                r->driver_path);
5132
5133         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5134                                driver->architecture,
5135                                driver->version,
5136                                driver->data_file,
5137                                r->data_file);
5138
5139         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5140                                driver->architecture,
5141                                driver->version,
5142                                driver->config_file,
5143                                r->config_file);
5144
5145         r->driver_attributes    = 0;
5146         r->config_version       = 0;
5147         r->driver_version       = 0;
5148
5149         return WERR_OK;
5150 }
5151 /********************************************************************
5152  * fill a spoolss_DriverInfo6 struct
5153  ********************************************************************/
5154
5155 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5156                                         struct spoolss_DriverInfo6 *r,
5157                                         const struct spoolss_DriverInfo8 *driver,
5158                                         const char *servername)
5159 {
5160         const char *cservername = canon_servername(servername);
5161         WERROR result;
5162
5163         r->version              = driver->version;
5164
5165         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5166         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5167         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5168         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5169
5170         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5171                                driver->architecture,
5172                                driver->version,
5173                                driver->driver_path,
5174                                r->driver_path);
5175
5176         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5177                                driver->architecture,
5178                                driver->version,
5179                                driver->data_file,
5180                                r->data_file);
5181
5182         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5183                                driver->architecture,
5184                                driver->version,
5185                                driver->config_file,
5186                                r->config_file);
5187
5188         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5189                                driver->architecture,
5190                                driver->version,
5191                                driver->help_file,
5192                                r->help_file);
5193
5194         FILL_DRIVER_STRING(mem_ctx,
5195                            driver->monitor_name,
5196                            r->monitor_name);
5197
5198         FILL_DRIVER_STRING(mem_ctx,
5199                            driver->default_datatype,
5200                            r->default_datatype);
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         result = string_array_from_driver_info(mem_ctx,
5213                                                driver->previous_names,
5214                                                &r->previous_names,
5215                                                NULL, NULL, 0);
5216         if (!W_ERROR_IS_OK(result)) {
5217                 return result;
5218         }
5219
5220         r->driver_date          = driver->driver_date;
5221         r->driver_version       = driver->driver_version;
5222
5223         FILL_DRIVER_STRING(mem_ctx,
5224                            driver->manufacturer_name,
5225                            r->manufacturer_name);
5226         FILL_DRIVER_STRING(mem_ctx,
5227                            driver->manufacturer_url,
5228                            r->manufacturer_url);
5229         FILL_DRIVER_STRING(mem_ctx,
5230                            driver->hardware_id,
5231                            r->hardware_id);
5232         FILL_DRIVER_STRING(mem_ctx,
5233                            driver->provider,
5234                            r->provider);
5235
5236         return WERR_OK;
5237 }
5238
5239 /********************************************************************
5240  * fill a spoolss_DriverInfo8 struct
5241  ********************************************************************/
5242
5243 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5244                                         struct spoolss_DriverInfo8 *r,
5245                                         const struct spoolss_DriverInfo8 *driver,
5246                                         const char *servername)
5247 {
5248         const char *cservername = canon_servername(servername);
5249         WERROR result;
5250
5251         r->version              = driver->version;
5252
5253         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5254         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5255         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5256         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5257
5258         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5259                                driver->architecture,
5260                                driver->version,
5261                                driver->driver_path,
5262                                r->driver_path);
5263
5264         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5265                                driver->architecture,
5266                                driver->version,
5267                                driver->data_file,
5268                                r->data_file);
5269
5270         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5271                                driver->architecture,
5272                                driver->version,
5273                                driver->config_file,
5274                                r->config_file);
5275
5276         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5277                                driver->architecture,
5278                                driver->version,
5279                                driver->help_file,
5280                                r->help_file);
5281
5282         FILL_DRIVER_STRING(mem_ctx,
5283                            driver->monitor_name,
5284                            r->monitor_name);
5285
5286         FILL_DRIVER_STRING(mem_ctx,
5287                            driver->default_datatype,
5288                            r->default_datatype);
5289
5290         result = string_array_from_driver_info(mem_ctx,
5291                                                driver->dependent_files,
5292                                                &r->dependent_files,
5293                                                cservername,
5294                                                driver->architecture,
5295                                                driver->version);
5296         if (!W_ERROR_IS_OK(result)) {
5297                 return result;
5298         }
5299
5300         result = string_array_from_driver_info(mem_ctx,
5301                                                driver->previous_names,
5302                                                &r->previous_names,
5303                                                NULL, NULL, 0);
5304         if (!W_ERROR_IS_OK(result)) {
5305                 return result;
5306         }
5307
5308         r->driver_date          = driver->driver_date;
5309         r->driver_version       = driver->driver_version;
5310
5311         FILL_DRIVER_STRING(mem_ctx,
5312                            driver->manufacturer_name,
5313                            r->manufacturer_name);
5314         FILL_DRIVER_STRING(mem_ctx,
5315                            driver->manufacturer_url,
5316                            r->manufacturer_url);
5317         FILL_DRIVER_STRING(mem_ctx,
5318                            driver->hardware_id,
5319                            r->hardware_id);
5320         FILL_DRIVER_STRING(mem_ctx,
5321                            driver->provider,
5322                            r->provider);
5323
5324         FILL_DRIVER_STRING(mem_ctx,
5325                            driver->print_processor,
5326                            r->print_processor);
5327         FILL_DRIVER_STRING(mem_ctx,
5328                            driver->vendor_setup,
5329                            r->vendor_setup);
5330
5331         result = string_array_from_driver_info(mem_ctx,
5332                                                driver->color_profiles,
5333                                                &r->color_profiles,
5334                                                NULL, NULL, 0);
5335         if (!W_ERROR_IS_OK(result)) {
5336                 return result;
5337         }
5338
5339         FILL_DRIVER_STRING(mem_ctx,
5340                            driver->inf_path,
5341                            r->inf_path);
5342
5343         r->printer_driver_attributes    = driver->printer_driver_attributes;
5344
5345         result = string_array_from_driver_info(mem_ctx,
5346                                                driver->core_driver_dependencies,
5347                                                &r->core_driver_dependencies,
5348                                                NULL, NULL, 0);
5349         if (!W_ERROR_IS_OK(result)) {
5350                 return result;
5351         }
5352
5353         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5354         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5355
5356         return WERR_OK;
5357 }
5358
5359 #if 0 /* disabled until marshalling issues are resolved - gd */
5360 /********************************************************************
5361  ********************************************************************/
5362
5363 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5364                                           struct spoolss_DriverFileInfo *r,
5365                                           const char *cservername,
5366                                           const char *file_name,
5367                                           enum spoolss_DriverFileType file_type,
5368                                           uint32_t file_version)
5369 {
5370         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5371                                           cservername, file_name);
5372         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5373         r->file_type    = file_type;
5374         r->file_version = file_version;
5375
5376         return WERR_OK;
5377 }
5378
5379 /********************************************************************
5380  ********************************************************************/
5381
5382 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5383                                                  const struct spoolss_DriverInfo8 *driver,
5384                                                  const char *cservername,
5385                                                  struct spoolss_DriverFileInfo **info_p,
5386                                                  uint32_t *count_p)
5387 {
5388         struct spoolss_DriverFileInfo *info = NULL;
5389         uint32_t count = 0;
5390         WERROR result;
5391         uint32_t i;
5392
5393         *info_p = NULL;
5394         *count_p = 0;
5395
5396         if (strlen(driver->driver_path)) {
5397                 info = talloc_realloc(mem_ctx, info,
5398                                             struct spoolss_DriverFileInfo,
5399                                             count + 1);
5400                 W_ERROR_HAVE_NO_MEMORY(info);
5401                 result = fill_spoolss_DriverFileInfo(info,
5402                                                      &info[count],
5403                                                      cservername,
5404                                                      driver->driver_path,
5405                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5406                                                      0);
5407                 W_ERROR_NOT_OK_RETURN(result);
5408                 count++;
5409         }
5410
5411         if (strlen(driver->config_file)) {
5412                 info = talloc_realloc(mem_ctx, info,
5413                                             struct spoolss_DriverFileInfo,
5414                                             count + 1);
5415                 W_ERROR_HAVE_NO_MEMORY(info);
5416                 result = fill_spoolss_DriverFileInfo(info,
5417                                                      &info[count],
5418                                                      cservername,
5419                                                      driver->config_file,
5420                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5421                                                      0);
5422                 W_ERROR_NOT_OK_RETURN(result);
5423                 count++;
5424         }
5425
5426         if (strlen(driver->data_file)) {
5427                 info = talloc_realloc(mem_ctx, info,
5428                                             struct spoolss_DriverFileInfo,
5429                                             count + 1);
5430                 W_ERROR_HAVE_NO_MEMORY(info);
5431                 result = fill_spoolss_DriverFileInfo(info,
5432                                                      &info[count],
5433                                                      cservername,
5434                                                      driver->data_file,
5435                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5436                                                      0);
5437                 W_ERROR_NOT_OK_RETURN(result);
5438                 count++;
5439         }
5440
5441         if (strlen(driver->help_file)) {
5442                 info = talloc_realloc(mem_ctx, info,
5443                                             struct spoolss_DriverFileInfo,
5444                                             count + 1);
5445                 W_ERROR_HAVE_NO_MEMORY(info);
5446                 result = fill_spoolss_DriverFileInfo(info,
5447                                                      &info[count],
5448                                                      cservername,
5449                                                      driver->help_file,
5450                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5451                                                      0);
5452                 W_ERROR_NOT_OK_RETURN(result);
5453                 count++;
5454         }
5455
5456         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5457                 info = talloc_realloc(mem_ctx, info,
5458                                             struct spoolss_DriverFileInfo,
5459                                             count + 1);
5460                 W_ERROR_HAVE_NO_MEMORY(info);
5461                 result = fill_spoolss_DriverFileInfo(info,
5462                                                      &info[count],
5463                                                      cservername,
5464                                                      driver->dependent_files[i],
5465                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5466                                                      0);
5467                 W_ERROR_NOT_OK_RETURN(result);
5468                 count++;
5469         }
5470
5471         *info_p = info;
5472         *count_p = count;
5473
5474         return WERR_OK;
5475 }
5476
5477 /********************************************************************
5478  * fill a spoolss_DriverInfo101 struct
5479  ********************************************************************/
5480
5481 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5482                                           struct spoolss_DriverInfo101 *r,
5483                                           const struct spoolss_DriverInfo8 *driver,
5484                                           const char *servername)
5485 {
5486         const char *cservername = canon_servername(servername);
5487         WERROR result;
5488
5489         r->version              = driver->version;
5490
5491         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5492         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5493         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5494         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5495
5496         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5497                                                     cservername,
5498                                                     &r->file_info,
5499                                                     &r->file_count);
5500         if (!W_ERROR_IS_OK(result)) {
5501                 return result;
5502         }
5503
5504         FILL_DRIVER_STRING(mem_ctx,
5505                            driver->monitor_name,
5506                            r->monitor_name);
5507
5508         FILL_DRIVER_STRING(mem_ctx,
5509                            driver->default_datatype,
5510                            r->default_datatype);
5511
5512         result = string_array_from_driver_info(mem_ctx,
5513                                                driver->previous_names,
5514                                                &r->previous_names,
5515                                                NULL, NULL, 0);
5516         if (!W_ERROR_IS_OK(result)) {
5517                 return result;
5518         }
5519
5520         r->driver_date          = driver->driver_date;
5521         r->driver_version       = driver->driver_version;
5522
5523         FILL_DRIVER_STRING(mem_ctx,
5524                            driver->manufacturer_name,
5525                            r->manufacturer_name);
5526         FILL_DRIVER_STRING(mem_ctx,
5527                            driver->manufacturer_url,
5528                            r->manufacturer_url);
5529         FILL_DRIVER_STRING(mem_ctx,
5530                            driver->hardware_id,
5531                            r->hardware_id);
5532         FILL_DRIVER_STRING(mem_ctx,
5533                            driver->provider,
5534                            r->provider);
5535
5536         return WERR_OK;
5537 }
5538 #endif
5539 /********************************************************************
5540  ********************************************************************/
5541
5542 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5543                                                   const struct auth_session_info *session_info,
5544                                                   struct messaging_context *msg_ctx,
5545                                                   uint32_t level,
5546                                                   union spoolss_DriverInfo *r,
5547                                                   int snum,
5548                                                   const char *servername,
5549                                                   const char *architecture,
5550                                                   uint32_t version)
5551 {
5552         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5553         struct spoolss_DriverInfo8 *driver;
5554         WERROR result;
5555         struct dcerpc_binding_handle *b;
5556         TALLOC_CTX *tmp_ctx = NULL;
5557
5558         if (level == 101) {
5559                 return WERR_UNKNOWN_LEVEL;
5560         }
5561
5562         tmp_ctx = talloc_new(mem_ctx);
5563         if (!tmp_ctx) {
5564                 return WERR_NOMEM;
5565         }
5566
5567         result = winreg_printer_binding_handle(tmp_ctx,
5568                                                session_info,
5569                                                msg_ctx,
5570                                                &b);
5571         if (!W_ERROR_IS_OK(result)) {
5572                 goto done;
5573         }
5574
5575         result = winreg_get_printer(tmp_ctx, b,
5576                                     lp_const_servicename(snum),
5577                                     &pinfo2);
5578
5579         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5580                 win_errstr(result)));
5581
5582         if (!W_ERROR_IS_OK(result)) {
5583                 result = WERR_INVALID_PRINTER_NAME;
5584                 goto done;
5585         }
5586
5587         result = winreg_get_driver(tmp_ctx, b,
5588                                    architecture,
5589                                    pinfo2->drivername, version, &driver);
5590
5591         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5592                 win_errstr(result)));
5593
5594         if (!W_ERROR_IS_OK(result)) {
5595                 /*
5596                  * Is this a W2k client ?
5597                  */
5598
5599                 if (version < 3) {
5600                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5601                         goto done;
5602                 }
5603
5604                 /* Yes - try again with a WinNT driver. */
5605                 version = 2;
5606                 result = winreg_get_driver(tmp_ctx, b,
5607                                            architecture,
5608                                            pinfo2->drivername,
5609                                            version, &driver);
5610                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5611                         win_errstr(result)));
5612                 if (!W_ERROR_IS_OK(result)) {
5613                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5614                         goto done;
5615                 }
5616         }
5617
5618         /* these are allocated on mem_ctx and not tmp_ctx because they are
5619          * the 'return value' and need to utlive this call */
5620         switch (level) {
5621         case 1:
5622                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5623                 break;
5624         case 2:
5625                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5626                 break;
5627         case 3:
5628                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5629                 break;
5630         case 4:
5631                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5632                 break;
5633         case 5:
5634                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5635                 break;
5636         case 6:
5637                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5638                 break;
5639         case 8:
5640                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5641                 break;
5642 #if 0 /* disabled until marshalling issues are resolved - gd */
5643         case 101:
5644                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5645                 break;
5646 #endif
5647         default:
5648                 result = WERR_UNKNOWN_LEVEL;
5649                 break;
5650         }
5651
5652 done:
5653         talloc_free(tmp_ctx);
5654         return result;
5655 }
5656
5657 /****************************************************************
5658  _spoolss_GetPrinterDriver2
5659 ****************************************************************/
5660
5661 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5662                                   struct spoolss_GetPrinterDriver2 *r)
5663 {
5664         struct printer_handle *printer;
5665         WERROR result;
5666         uint32_t version = r->in.client_major_version;
5667
5668         int snum;
5669
5670         /* that's an [in out] buffer */
5671
5672         if (!r->in.buffer && (r->in.offered != 0)) {
5673                 return WERR_INVALID_PARAM;
5674         }
5675
5676         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5677
5678         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5679                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5680                 return WERR_INVALID_PRINTER_NAME;
5681         }
5682
5683         *r->out.needed = 0;
5684         *r->out.server_major_version = 0;
5685         *r->out.server_minor_version = 0;
5686
5687         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5688                 return WERR_BADFID;
5689         }
5690
5691         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5692                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5693                         "downgrading to v3\n"));
5694                 version = SPOOLSS_DRIVER_VERSION_200X;
5695         }
5696
5697         result = construct_printer_driver_info_level(p->mem_ctx,
5698                                                      get_session_info_system(),
5699                                                      p->msg_ctx,
5700                                                      r->in.level, r->out.info,
5701                                                      snum, printer->servername,
5702                                                      r->in.architecture,
5703                                                      version);
5704         if (!W_ERROR_IS_OK(result)) {
5705                 TALLOC_FREE(r->out.info);
5706                 return result;
5707         }
5708
5709         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5710                                                r->out.info, r->in.level);
5711         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5712
5713         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5714 }
5715
5716
5717 /****************************************************************
5718  _spoolss_StartPagePrinter
5719 ****************************************************************/
5720
5721 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5722                                  struct spoolss_StartPagePrinter *r)
5723 {
5724         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5725
5726         if (!Printer) {
5727                 DEBUG(3,("_spoolss_StartPagePrinter: "
5728                         "Error in startpageprinter printer handle\n"));
5729                 return WERR_BADFID;
5730         }
5731
5732         Printer->page_started = true;
5733         return WERR_OK;
5734 }
5735
5736 /****************************************************************
5737  _spoolss_EndPagePrinter
5738 ****************************************************************/
5739
5740 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5741                                struct spoolss_EndPagePrinter *r)
5742 {
5743         int snum;
5744
5745         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5746
5747         if (!Printer) {
5748                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5749                         OUR_HANDLE(r->in.handle)));
5750                 return WERR_BADFID;
5751         }
5752
5753         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5754                 return WERR_BADFID;
5755
5756         Printer->page_started = false;
5757         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5758
5759         return WERR_OK;
5760 }
5761
5762 /****************************************************************
5763  _spoolss_StartDocPrinter
5764 ****************************************************************/
5765
5766 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5767                                 struct spoolss_StartDocPrinter *r)
5768 {
5769         struct spoolss_DocumentInfo1 *info_1;
5770         int snum;
5771         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5772         WERROR werr;
5773         char *rhost;
5774         int rc;
5775
5776         if (!Printer) {
5777                 DEBUG(2,("_spoolss_StartDocPrinter: "
5778                         "Invalid handle (%s:%u:%u)\n",
5779                         OUR_HANDLE(r->in.handle)));
5780                 return WERR_BADFID;
5781         }
5782
5783         if (Printer->jobid) {
5784                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5785                           "StartDocPrinter called twice! "
5786                           "(existing jobid = %d)\n", Printer->jobid));
5787                 return WERR_INVALID_HANDLE;
5788         }
5789
5790         if (r->in.level != 1) {
5791                 return WERR_UNKNOWN_LEVEL;
5792         }
5793
5794         info_1 = r->in.info.info1;
5795
5796         /*
5797          * a nice thing with NT is it doesn't listen to what you tell it.
5798          * when asked to send _only_ RAW datas, it tries to send datas
5799          * in EMF format.
5800          *
5801          * So I add checks like in NT Server ...
5802          */
5803
5804         if (info_1->datatype) {
5805                 /*
5806                  * The v4 driver model used in Windows 8 declares print jobs
5807                  * intended to bypass the XPS processing layer by setting
5808                  * datatype to "XPS_PASS" instead of "RAW".
5809                  */
5810                 if ((strcmp(info_1->datatype, "RAW") != 0)
5811                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5812                         *r->out.job_id = 0;
5813                         return WERR_INVALID_DATATYPE;
5814                 }
5815         }
5816
5817         /* get the share number of the printer */
5818         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5819                 return WERR_BADFID;
5820         }
5821
5822         rc = get_remote_hostname(p->remote_address,
5823                                  &rhost,
5824                                  p->mem_ctx);
5825         if (rc < 0) {
5826                 return WERR_NOMEM;
5827         }
5828         if (strequal(rhost,"UNKNOWN")) {
5829                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5830                                                          p->mem_ctx);
5831                 if (rhost == NULL) {
5832                         return WERR_NOMEM;
5833                 }
5834         }
5835
5836         werr = print_job_start(p->session_info,
5837                                p->msg_ctx,
5838                                rhost,
5839                                snum,
5840                                info_1->document_name,
5841                                info_1->output_file,
5842                                Printer->devmode,
5843                                &Printer->jobid);
5844
5845         /* An error occured in print_job_start() so return an appropriate
5846            NT error code. */
5847
5848         if (!W_ERROR_IS_OK(werr)) {
5849                 return werr;
5850         }
5851
5852         Printer->document_started = true;
5853         *r->out.job_id = Printer->jobid;
5854
5855         return WERR_OK;
5856 }
5857
5858 /****************************************************************
5859  _spoolss_EndDocPrinter
5860 ****************************************************************/
5861
5862 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5863                               struct spoolss_EndDocPrinter *r)
5864 {
5865         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5866         NTSTATUS status;
5867         int snum;
5868
5869         if (!Printer) {
5870                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5871                         OUR_HANDLE(r->in.handle)));
5872                 return WERR_BADFID;
5873         }
5874
5875         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5876                 return WERR_BADFID;
5877         }
5878
5879         Printer->document_started = false;
5880         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5881         if (!NT_STATUS_IS_OK(status)) {
5882                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5883                           "print_job_end failed [%s]\n",
5884                           nt_errstr(status)));
5885         }
5886
5887         Printer->jobid = 0;
5888         return ntstatus_to_werror(status);
5889 }
5890
5891 /****************************************************************
5892  _spoolss_WritePrinter
5893 ****************************************************************/
5894
5895 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5896                              struct spoolss_WritePrinter *r)
5897 {
5898         ssize_t buffer_written;
5899         int snum;
5900         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5901
5902         if (!Printer) {
5903                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5904                         OUR_HANDLE(r->in.handle)));
5905                 *r->out.num_written = r->in._data_size;
5906                 return WERR_BADFID;
5907         }
5908
5909         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5910                 return WERR_BADFID;
5911
5912         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5913         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5914                                                    snum, Printer->jobid,
5915                                                    (const char *)r->in.data.data,
5916                                                    (size_t)r->in._data_size);
5917         if (buffer_written == (ssize_t)-1) {
5918                 *r->out.num_written = 0;
5919                 if (errno == ENOSPC)
5920                         return WERR_NO_SPOOL_SPACE;
5921                 else
5922                         return WERR_ACCESS_DENIED;
5923         }
5924
5925         *r->out.num_written = r->in._data_size;
5926
5927         return WERR_OK;
5928 }
5929
5930 /********************************************************************
5931  * api_spoolss_getprinter
5932  * called from the spoolss dispatcher
5933  *
5934  ********************************************************************/
5935
5936 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5937                               struct pipes_struct *p)
5938 {
5939         const struct auth_session_info *session_info = p->session_info;
5940         int snum;
5941         WERROR errcode = WERR_BADFUNC;
5942         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5943
5944         if (!Printer) {
5945                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5946                         OUR_HANDLE(handle)));
5947                 return WERR_BADFID;
5948         }
5949
5950         if (!get_printer_snum(p, handle, &snum, NULL))
5951                 return WERR_BADFID;
5952
5953         switch (command) {
5954         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5955                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5956                 break;
5957         case SPOOLSS_PRINTER_CONTROL_RESUME:
5958         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5959                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5960                 break;
5961         case SPOOLSS_PRINTER_CONTROL_PURGE:
5962                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5963                 break;
5964         default:
5965                 return WERR_UNKNOWN_LEVEL;
5966         }
5967
5968         return errcode;
5969 }
5970
5971
5972 /****************************************************************
5973  _spoolss_AbortPrinter
5974  * From MSDN: "Deletes printer's spool file if printer is configured
5975  * for spooling"
5976 ****************************************************************/
5977
5978 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5979                              struct spoolss_AbortPrinter *r)
5980 {
5981         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5982         int             snum;
5983         WERROR          errcode = WERR_OK;
5984
5985         if (!Printer) {
5986                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5987                         OUR_HANDLE(r->in.handle)));
5988                 return WERR_BADFID;
5989         }
5990
5991         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5992                 return WERR_BADFID;
5993
5994         if (!Printer->document_started) {
5995                 return WERR_SPL_NO_STARTDOC;
5996         }
5997
5998         errcode = print_job_delete(p->session_info,
5999                                    p->msg_ctx,
6000                                    snum,
6001                                    Printer->jobid);
6002
6003         return errcode;
6004 }
6005
6006 /********************************************************************
6007  * called by spoolss_api_setprinter
6008  * when updating a printer description
6009  ********************************************************************/
6010
6011 static WERROR update_printer_sec(struct policy_handle *handle,
6012                                  struct pipes_struct *p,
6013                                  struct sec_desc_buf *secdesc_ctr)
6014 {
6015         struct spoolss_security_descriptor *new_secdesc = NULL;
6016         struct spoolss_security_descriptor *old_secdesc = NULL;
6017         const char *printer;
6018         WERROR result;
6019         int snum;
6020         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6021         struct dcerpc_binding_handle *b;
6022         TALLOC_CTX *tmp_ctx = NULL;
6023
6024         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6025                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6026                          OUR_HANDLE(handle)));
6027
6028                 result = WERR_BADFID;
6029                 goto done;
6030         }
6031
6032         if (secdesc_ctr == NULL) {
6033                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6034                 result = WERR_INVALID_PARAM;
6035                 goto done;
6036         }
6037         printer = lp_const_servicename(snum);
6038
6039         /* Check the user has permissions to change the security
6040            descriptor.  By experimentation with two NT machines, the user
6041            requires Full Access to the printer to change security
6042            information. */
6043
6044         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6045                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6046                 result = WERR_ACCESS_DENIED;
6047                 goto done;
6048         }
6049
6050         tmp_ctx = talloc_new(p->mem_ctx);
6051         if (!tmp_ctx) {
6052                 return WERR_NOMEM;
6053         }
6054
6055         result = winreg_printer_binding_handle(tmp_ctx,
6056                                                get_session_info_system(),
6057                                                p->msg_ctx,
6058                                                &b);
6059         if (!W_ERROR_IS_OK(result)) {
6060                 goto done;
6061         }
6062
6063         /* NT seems to like setting the security descriptor even though
6064            nothing may have actually changed. */
6065         result = winreg_get_printer_secdesc(tmp_ctx, b,
6066                                             printer,
6067                                             &old_secdesc);
6068         if (!W_ERROR_IS_OK(result)) {
6069                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6070                 result = WERR_BADFID;
6071                 goto done;
6072         }
6073
6074         if (DEBUGLEVEL >= 10) {
6075                 struct security_acl *the_acl;
6076                 int i;
6077
6078                 the_acl = old_secdesc->dacl;
6079                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6080                            printer, the_acl->num_aces));
6081
6082                 for (i = 0; i < the_acl->num_aces; i++) {
6083                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6084                                            &the_acl->aces[i].trustee),
6085                                   the_acl->aces[i].access_mask));
6086                 }
6087
6088                 the_acl = secdesc_ctr->sd->dacl;
6089
6090                 if (the_acl) {
6091                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6092                                    printer, the_acl->num_aces));
6093
6094                         for (i = 0; i < the_acl->num_aces; i++) {
6095                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6096                                                    &the_acl->aces[i].trustee),
6097                                            the_acl->aces[i].access_mask));
6098                         }
6099                 } else {
6100                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6101                 }
6102         }
6103
6104         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6105         if (new_secdesc == NULL) {
6106                 result = WERR_NOMEM;
6107                 goto done;
6108         }
6109
6110         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6111                 result = WERR_OK;
6112                 goto done;
6113         }
6114
6115         result = winreg_set_printer_secdesc(tmp_ctx, b,
6116                                             printer,
6117                                             new_secdesc);
6118
6119 done:
6120         talloc_free(tmp_ctx);
6121         return result;
6122 }
6123
6124 /********************************************************************
6125  Canonicalize printer info from a client
6126  ********************************************************************/
6127
6128 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6129                              struct spoolss_SetPrinterInfo2 *info2,
6130                              int snum)
6131 {
6132         fstring printername;
6133         const char *p;
6134
6135         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6136                 "portname=%s drivername=%s comment=%s location=%s\n",
6137                 info2->servername, info2->printername, info2->sharename,
6138                 info2->portname, info2->drivername, info2->comment,
6139                 info2->location));
6140
6141         /* we force some elements to "correct" values */
6142         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6143         if (info2->servername == NULL) {
6144                 return false;
6145         }
6146         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6147         if (info2->sharename == NULL) {
6148                 return false;
6149         }
6150
6151         /* check to see if we allow printername != sharename */
6152         if (lp_force_printername(snum)) {
6153                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6154                                         lp_netbios_name(), info2->sharename);
6155         } else {
6156                 /* make sure printername is in \\server\printername format */
6157                 fstrcpy(printername, info2->printername);
6158                 p = printername;
6159                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6160                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6161                                 p++;
6162                 }
6163
6164                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6165                                         lp_netbios_name(), p);
6166         }
6167         if (info2->printername == NULL) {
6168                 return false;
6169         }
6170
6171         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6172         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6173
6174         return true;
6175 }
6176
6177 /****************************************************************************
6178 ****************************************************************************/
6179
6180 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6181 {
6182         char *cmd = lp_addport_cmd(talloc_tos());
6183         char *command = NULL;
6184         int ret;
6185         bool is_print_op = false;
6186
6187         if ( !*cmd ) {
6188                 return WERR_ACCESS_DENIED;
6189         }
6190
6191         command = talloc_asprintf(ctx,
6192                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6193         if (!command) {
6194                 return WERR_NOMEM;
6195         }
6196
6197         if ( token )
6198                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6199
6200         DEBUG(10,("Running [%s]\n", command));
6201
6202         /********* BEGIN SePrintOperatorPrivilege **********/
6203
6204         if ( is_print_op )
6205                 become_root();
6206
6207         ret = smbrun(command, NULL);
6208
6209         if ( is_print_op )
6210                 unbecome_root();
6211
6212         /********* END SePrintOperatorPrivilege **********/
6213
6214         DEBUGADD(10,("returned [%d]\n", ret));
6215
6216         TALLOC_FREE(command);
6217
6218         if ( ret != 0 ) {
6219                 return WERR_ACCESS_DENIED;
6220         }
6221
6222         return WERR_OK;
6223 }
6224
6225 /****************************************************************************
6226 ****************************************************************************/
6227
6228 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6229                                    int snum)
6230 {
6231         /*
6232          * As we do not know if we are embedded in the file server process
6233          * or not, we have to pretend that all shares are in use.
6234          */
6235         return true;
6236 }
6237
6238 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6239                              struct spoolss_SetPrinterInfo2 *info2,
6240                              const char *remote_machine,
6241                              struct messaging_context *msg_ctx)
6242 {
6243         char *cmd = lp_addprinter_cmd(talloc_tos());
6244         char **qlines;
6245         char *command = NULL;
6246         int numlines;
6247         int ret;
6248         int fd;
6249         bool is_print_op = false;
6250
6251         if (!remote_machine) {
6252                 return false;
6253         }
6254
6255         command = talloc_asprintf(ctx,
6256                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6257                         cmd, info2->printername, info2->sharename,
6258                         info2->portname, info2->drivername,
6259                         info2->location, info2->comment, remote_machine);
6260         if (!command) {
6261                 return false;
6262         }
6263
6264         if ( token )
6265                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6266
6267         DEBUG(10,("Running [%s]\n", command));
6268
6269         /********* BEGIN SePrintOperatorPrivilege **********/
6270
6271         if ( is_print_op )
6272                 become_root();
6273
6274         if ( (ret = smbrun(command, &fd)) == 0 ) {
6275                 /* Tell everyone we updated smb.conf. */
6276                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6277         }
6278
6279         if ( is_print_op )
6280                 unbecome_root();
6281
6282         /********* END SePrintOperatorPrivilege **********/
6283
6284         DEBUGADD(10,("returned [%d]\n", ret));
6285
6286         TALLOC_FREE(command);
6287
6288         if ( ret != 0 ) {
6289                 if (fd != -1)
6290                         close(fd);
6291                 return false;
6292         }
6293
6294         /* reload our services immediately */
6295         become_root();
6296         reload_services(NULL, spoolss_conn_snum_used, false);
6297         unbecome_root();
6298
6299         numlines = 0;
6300         /* Get lines and convert them back to dos-codepage */
6301         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6302         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6303         close(fd);
6304
6305         /* Set the portname to what the script says the portname should be. */
6306         /* but don't require anything to be return from the script exit a good error code */
6307
6308         if (numlines) {
6309                 /* Set the portname to what the script says the portname should be. */
6310                 info2->portname = talloc_strdup(ctx, qlines[0]);
6311                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6312         }
6313
6314         TALLOC_FREE(qlines);
6315         return true;
6316 }
6317
6318 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6319                                const struct auth_session_info *session_info,
6320                                struct messaging_context *msg_ctx,
6321                                int snum,
6322                                struct spoolss_SetPrinterInfo2 *printer,
6323                                struct spoolss_PrinterInfo2 *old_printer)
6324 {
6325         bool force_update = (old_printer == NULL);
6326         const char *dnsdomname;
6327         const char *longname;
6328         const char *uncname;
6329         const char *spooling;
6330         DATA_BLOB buffer;
6331         WERROR result = WERR_OK;
6332         struct dcerpc_binding_handle *b;
6333         TALLOC_CTX *tmp_ctx;
6334         bool ok;
6335
6336         tmp_ctx = talloc_new(mem_ctx);
6337         if (!tmp_ctx) {
6338                 return WERR_NOMEM;
6339         }
6340
6341         result = winreg_printer_binding_handle(tmp_ctx,
6342                                                session_info,
6343                                                msg_ctx,
6344                                                &b);
6345         if (!W_ERROR_IS_OK(result)) {
6346                 goto done;
6347         }
6348
6349         if (printer->drivername != NULL &&
6350             (force_update ||
6351              !strequal(printer->drivername, old_printer->drivername))) {
6352                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6353                 if (!ok) {
6354                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6355                         result = WERR_INVALID_DATA;
6356                         goto done;
6357                 }
6358                 result = winreg_set_printer_dataex(tmp_ctx, b,
6359                                           printer->sharename,
6360                                           SPOOL_DSSPOOLER_KEY,
6361                                           SPOOL_REG_DRIVERNAME,
6362                                           REG_SZ,
6363                                           buffer.data,
6364                                           buffer.length);
6365                 if (!W_ERROR_IS_OK(result)) {
6366                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6367                         goto done;
6368                 }
6369
6370                 if (!force_update) {
6371                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6372                                 printer->drivername));
6373
6374                         notify_printer_driver(server_event_context(), msg_ctx,
6375                                               snum, printer->drivername ?
6376                                               printer->drivername : "");
6377                 }
6378         }
6379
6380         if (printer->comment != NULL &&
6381             (force_update ||
6382              !strequal(printer->comment, old_printer->comment))) {
6383                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6384                 if (!ok) {
6385                         DEBUG(0, ("comment data corrupted\n"));
6386                         result = WERR_INVALID_DATA;
6387                         goto done;
6388                 }
6389                 result = winreg_set_printer_dataex(tmp_ctx, b,
6390                                           printer->sharename,
6391                                           SPOOL_DSSPOOLER_KEY,
6392                                           SPOOL_REG_DESCRIPTION,
6393                                           REG_SZ,
6394                                           buffer.data,
6395                                           buffer.length);
6396                 if (!W_ERROR_IS_OK(result)) {
6397                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6398                         goto done;
6399                 }
6400
6401                 if (!force_update) {
6402                         notify_printer_comment(server_event_context(), msg_ctx,
6403                                                snum, printer->comment ?
6404                                                printer->comment : "");
6405                 }
6406         }
6407
6408         if (printer->sharename != NULL &&
6409             (force_update ||
6410              !strequal(printer->sharename, old_printer->sharename))) {
6411                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6412                 if (!ok) {
6413                         DEBUG(0, ("sharename data corrupted\n"));
6414                         result = WERR_INVALID_DATA;
6415                         goto done;
6416                 }
6417                 result = winreg_set_printer_dataex(tmp_ctx, b,
6418                                           printer->sharename,
6419                                           SPOOL_DSSPOOLER_KEY,
6420                                           SPOOL_REG_PRINTSHARENAME,
6421                                           REG_SZ,
6422                                           buffer.data,
6423                                           buffer.length);
6424                 if (!W_ERROR_IS_OK(result)) {
6425                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6426                         goto done;
6427                 }
6428
6429                 if (!force_update) {
6430                         notify_printer_sharename(server_event_context(),
6431                                                  msg_ctx,
6432                                                  snum, printer->sharename ?
6433                                                  printer->sharename : "");
6434                 }
6435         }
6436
6437         if (printer->printername != NULL &&
6438             (force_update ||
6439              !strequal(printer->printername, old_printer->printername))) {
6440                 const char *p;
6441
6442                 p = strrchr(printer->printername, '\\' );
6443                 if (p != NULL) {
6444                         p++;
6445                 } else {
6446                         p = printer->printername;
6447                 }
6448
6449                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6450                 if (!ok) {
6451                         DEBUG(0, ("printername data corrupted\n"));
6452                         result = WERR_INVALID_DATA;
6453                         goto done;
6454                 }
6455                 result = winreg_set_printer_dataex(tmp_ctx, b,
6456                                           printer->sharename,
6457                                           SPOOL_DSSPOOLER_KEY,
6458                                           SPOOL_REG_PRINTERNAME,
6459                                           REG_SZ,
6460                                           buffer.data,
6461                                           buffer.length);
6462                 if (!W_ERROR_IS_OK(result)) {
6463                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6464                         goto done;
6465                 }
6466
6467                 if (!force_update) {
6468                         notify_printer_printername(server_event_context(),
6469                                                    msg_ctx, snum, p ? p : "");
6470                 }
6471         }
6472
6473         if (printer->portname != NULL &&
6474             (force_update ||
6475              !strequal(printer->portname, old_printer->portname))) {
6476                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6477                 if (!ok) {
6478                         DEBUG(0, ("portname data corrupted\n"));
6479                         result = WERR_INVALID_DATA;
6480                         goto done;
6481                 }
6482                 result = winreg_set_printer_dataex(tmp_ctx, b,
6483                                           printer->sharename,
6484                                           SPOOL_DSSPOOLER_KEY,
6485                                           SPOOL_REG_PORTNAME,
6486                                           REG_SZ,
6487                                           buffer.data,
6488                                           buffer.length);
6489                 if (!W_ERROR_IS_OK(result)) {
6490                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6491                         goto done;
6492                 }
6493
6494                 if (!force_update) {
6495                         notify_printer_port(server_event_context(),
6496                                             msg_ctx, snum, printer->portname ?
6497                                             printer->portname : "");
6498                 }
6499         }
6500
6501         if (printer->location != NULL &&
6502             (force_update ||
6503              !strequal(printer->location, old_printer->location))) {
6504                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6505                 if (!ok) {
6506                         DEBUG(0, ("location data corrupted\n"));
6507                         result = WERR_INVALID_DATA;
6508                         goto done;
6509                 }
6510                 result = winreg_set_printer_dataex(tmp_ctx, b,
6511                                           printer->sharename,
6512                                           SPOOL_DSSPOOLER_KEY,
6513                                           SPOOL_REG_LOCATION,
6514                                           REG_SZ,
6515                                           buffer.data,
6516                                           buffer.length);
6517                 if (!W_ERROR_IS_OK(result)) {
6518                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6519                         goto done;
6520                 }
6521
6522                 if (!force_update) {
6523                         notify_printer_location(server_event_context(),
6524                                                 msg_ctx, snum,
6525                                                 printer->location ?
6526                                                 printer->location : "");
6527                 }
6528         }
6529
6530         if (printer->sepfile != NULL &&
6531             (force_update ||
6532              !strequal(printer->sepfile, old_printer->sepfile))) {
6533                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6534                 if (!ok) {
6535                         DEBUG(0, ("sepfile data corrupted\n"));
6536                         result = WERR_INVALID_DATA;
6537                         goto done;
6538                 }
6539                 result = winreg_set_printer_dataex(tmp_ctx, b,
6540                                           printer->sharename,
6541                                           SPOOL_DSSPOOLER_KEY,
6542                                           SPOOL_REG_PRINTSEPARATORFILE,
6543                                           REG_SZ,
6544                                           buffer.data,
6545                                           buffer.length);
6546                 if (!W_ERROR_IS_OK(result)) {
6547                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6548                         goto done;
6549                 }
6550
6551                 if (!force_update) {
6552                         notify_printer_sepfile(server_event_context(),
6553                                                msg_ctx, snum,
6554                                                printer->sepfile ?
6555                                                printer->sepfile : "");
6556                 }
6557         }
6558
6559         if (printer->starttime != 0 &&
6560             (force_update ||
6561              printer->starttime != old_printer->starttime)) {
6562                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6563                 SIVAL(buffer.data, 0, printer->starttime);
6564                 result = winreg_set_printer_dataex(tmp_ctx, b,
6565                                           printer->sharename,
6566                                           SPOOL_DSSPOOLER_KEY,
6567                                           SPOOL_REG_PRINTSTARTTIME,
6568                                           REG_DWORD,
6569                                           buffer.data,
6570                                           buffer.length);
6571                 if (!W_ERROR_IS_OK(result)) {
6572                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6573                         goto done;
6574                 }
6575         }
6576
6577         if (printer->untiltime != 0 &&
6578             (force_update ||
6579              printer->untiltime != old_printer->untiltime)) {
6580                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6581                 SIVAL(buffer.data, 0, printer->untiltime);
6582                 result = winreg_set_printer_dataex(tmp_ctx, b,
6583                                           printer->sharename,
6584                                           SPOOL_DSSPOOLER_KEY,
6585                                           SPOOL_REG_PRINTENDTIME,
6586                                           REG_DWORD,
6587                                           buffer.data,
6588                                           buffer.length);
6589                 if (!W_ERROR_IS_OK(result)) {
6590                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6591                         goto done;
6592                 }
6593         }
6594
6595         if (force_update || printer->priority != old_printer->priority) {
6596                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6597                 SIVAL(buffer.data, 0, printer->priority);
6598                 result = winreg_set_printer_dataex(tmp_ctx, b,
6599                                           printer->sharename,
6600                                           SPOOL_DSSPOOLER_KEY,
6601                                           SPOOL_REG_PRIORITY,
6602                                           REG_DWORD,
6603                                           buffer.data,
6604                                           buffer.length);
6605                 if (!W_ERROR_IS_OK(result)) {
6606                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6607                         goto done;
6608                 }
6609         }
6610
6611         if (force_update || printer->attributes != old_printer->attributes) {
6612                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6613                 SIVAL(buffer.data, 0, (printer->attributes &
6614                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6615                 result = winreg_set_printer_dataex(tmp_ctx, b,
6616                                           printer->sharename,
6617                                           SPOOL_DSSPOOLER_KEY,
6618                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6619                                           REG_DWORD,
6620                                           buffer.data,
6621                                           buffer.length);
6622                 if (!W_ERROR_IS_OK(result)) {
6623                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6624                         goto done;
6625                 }
6626
6627                 switch (printer->attributes & 0x3) {
6628                         case 0:
6629                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6630                                 break;
6631                         case 1:
6632                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6633                                 break;
6634                         case 2:
6635                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6636                                 break;
6637                         default:
6638                                 spooling = "unknown";
6639                 }
6640                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6641                 if (!ok) {
6642                         DEBUG(0, ("printSpooling data corrupted\n"));
6643                         result = WERR_INVALID_DATA;
6644                         goto done;
6645                 }
6646                 winreg_set_printer_dataex(tmp_ctx, b,
6647                                           printer->sharename,
6648                                           SPOOL_DSSPOOLER_KEY,
6649                                           SPOOL_REG_PRINTSPOOLING,
6650                                           REG_SZ,
6651                                           buffer.data,
6652                                           buffer.length);
6653         }
6654
6655         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6656         if (!ok) {
6657                 DEBUG(0, ("shortServerName data corrupted\n"));
6658                 result = WERR_INVALID_DATA;
6659                 goto done;
6660         }
6661         result = winreg_set_printer_dataex(tmp_ctx, b,
6662                                   printer->sharename,
6663                                   SPOOL_DSSPOOLER_KEY,
6664                                   SPOOL_REG_SHORTSERVERNAME,
6665                                   REG_SZ,
6666                                   buffer.data,
6667                                   buffer.length);
6668         if (!W_ERROR_IS_OK(result)) {
6669                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6670                 goto done;
6671         }
6672
6673         dnsdomname = get_mydnsfullname();
6674         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6675                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6676         } else {
6677                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6678         }
6679         if (longname == NULL) {
6680                 result = WERR_NOMEM;
6681                 goto done;
6682         }
6683
6684         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6685         if (!ok) {
6686                 DEBUG(0, ("longname data corrupted\n"));
6687                 result = WERR_INVALID_DATA;
6688                 goto done;
6689         }
6690         result = winreg_set_printer_dataex(tmp_ctx, b,
6691                                            printer->sharename,
6692                                            SPOOL_DSSPOOLER_KEY,
6693                                            SPOOL_REG_SERVERNAME,
6694                                            REG_SZ,
6695                                            buffer.data,
6696                                            buffer.length);
6697         if (!W_ERROR_IS_OK(result)) {
6698                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6699                 goto done;
6700         }
6701
6702         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6703                                   lp_netbios_name(), printer->sharename);
6704         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6705         if (!ok) {
6706                 DEBUG(0, ("uncName data corrupted\n"));
6707                 result = WERR_INVALID_DATA;
6708                 goto done;
6709         }
6710         result = winreg_set_printer_dataex(tmp_ctx, b,
6711                                   printer->sharename,
6712                                   SPOOL_DSSPOOLER_KEY,
6713                                   SPOOL_REG_UNCNAME,
6714                                   REG_SZ,
6715                                   buffer.data,
6716                                   buffer.length);
6717         if (!W_ERROR_IS_OK(result)) {
6718                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6719                 goto done;
6720         }
6721
6722 done:
6723         talloc_free(tmp_ctx);
6724         return result;
6725 }
6726
6727 /********************************************************************
6728  * Called by spoolss_api_setprinter
6729  * when updating a printer description.
6730  ********************************************************************/
6731
6732 static WERROR update_printer(struct pipes_struct *p,
6733                              struct policy_handle *handle,
6734                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6735                              struct spoolss_DeviceMode *devmode)
6736 {
6737         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6738         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6739         struct spoolss_PrinterInfo2 *old_printer;
6740         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6741         int snum;
6742         WERROR result = WERR_OK;
6743         TALLOC_CTX *tmp_ctx;
6744         struct dcerpc_binding_handle *b;
6745
6746         DEBUG(8,("update_printer\n"));
6747
6748         tmp_ctx = talloc_new(p->mem_ctx);
6749         if (tmp_ctx == NULL) {
6750                 return WERR_NOMEM;
6751         }
6752
6753         if (!Printer) {
6754                 result = WERR_BADFID;
6755                 goto done;
6756         }
6757
6758         if (!get_printer_snum(p, handle, &snum, NULL)) {
6759                 result = WERR_BADFID;
6760                 goto done;
6761         }
6762
6763         result = winreg_printer_binding_handle(tmp_ctx,
6764                                                get_session_info_system(),
6765                                                p->msg_ctx,
6766                                                &b);
6767         if (!W_ERROR_IS_OK(result)) {
6768                 goto done;
6769         }
6770
6771         result = winreg_get_printer(tmp_ctx, b,
6772                                     lp_const_servicename(snum),
6773                                     &old_printer);
6774         if (!W_ERROR_IS_OK(result)) {
6775                 result = WERR_BADFID;
6776                 goto done;
6777         }
6778
6779         /* Do sanity check on the requested changes for Samba */
6780         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6781                 result = WERR_INVALID_PARAM;
6782                 goto done;
6783         }
6784
6785         /* FIXME!!! If the driver has changed we really should verify that
6786            it is installed before doing much else   --jerry */
6787
6788         /* Check calling user has permission to update printer description */
6789         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6790                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6791                 result = WERR_ACCESS_DENIED;
6792                 goto done;
6793         }
6794
6795         /* Call addprinter hook */
6796         /* Check changes to see if this is really needed */
6797
6798         if (*lp_addprinter_cmd(talloc_tos()) &&
6799                         (!strequal(printer->drivername, old_printer->drivername) ||
6800                          !strequal(printer->comment, old_printer->comment) ||
6801                          !strequal(printer->portname, old_printer->portname) ||
6802                          !strequal(printer->location, old_printer->location)) )
6803         {
6804                 char *raddr;
6805
6806                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6807                                                          p->mem_ctx);
6808                 if (raddr == NULL) {
6809                         return WERR_NOMEM;
6810                 }
6811
6812                 /* add_printer_hook() will call reload_services() */
6813                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6814                                       printer, raddr,
6815                                       p->msg_ctx)) {
6816                         result = WERR_ACCESS_DENIED;
6817                         goto done;
6818                 }
6819         }
6820
6821         result = update_dsspooler(tmp_ctx,
6822                                   get_session_info_system(),
6823                                   p->msg_ctx,
6824                                   snum,
6825                                   printer,
6826                                   old_printer);
6827         if (!W_ERROR_IS_OK(result)) {
6828                 goto done;
6829         }
6830
6831         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6832
6833         if (devmode == NULL) {
6834                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6835         }
6836         result = winreg_update_printer(tmp_ctx, b,
6837                                        printer->sharename,
6838                                        printer_mask,
6839                                        printer,
6840                                        devmode,
6841                                        NULL);
6842
6843 done:
6844         talloc_free(tmp_ctx);
6845
6846         return result;
6847 }
6848
6849 /****************************************************************************
6850 ****************************************************************************/
6851 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6852                                            struct policy_handle *handle,
6853                                            struct spoolss_SetPrinterInfo7 *info7)
6854 {
6855 #ifdef HAVE_ADS
6856         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6857         WERROR result;
6858         int snum;
6859         struct printer_handle *Printer;
6860
6861         if ( lp_security() != SEC_ADS ) {
6862                 return WERR_UNKNOWN_LEVEL;
6863         }
6864
6865         Printer = find_printer_index_by_hnd(p, handle);
6866
6867         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6868
6869         if (!Printer)
6870                 return WERR_BADFID;
6871
6872         if (!get_printer_snum(p, handle, &snum, NULL))
6873                 return WERR_BADFID;
6874
6875         result = winreg_get_printer_internal(p->mem_ctx,
6876                                     get_session_info_system(),
6877                                     p->msg_ctx,
6878                                     lp_servicename(talloc_tos(), snum),
6879                                     &pinfo2);
6880         if (!W_ERROR_IS_OK(result)) {
6881                 return WERR_BADFID;
6882         }
6883
6884         nt_printer_publish(pinfo2,
6885                            get_session_info_system(),
6886                            p->msg_ctx,
6887                            pinfo2,
6888                            info7->action);
6889
6890         TALLOC_FREE(pinfo2);
6891         return WERR_OK;
6892 #else
6893         return WERR_UNKNOWN_LEVEL;
6894 #endif
6895 }
6896
6897 /********************************************************************
6898  ********************************************************************/
6899
6900 static WERROR update_printer_devmode(struct pipes_struct *p,
6901                                      struct policy_handle *handle,
6902                                      struct spoolss_DeviceMode *devmode)
6903 {
6904         int snum;
6905         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6906         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6907
6908         DEBUG(8,("update_printer_devmode\n"));
6909
6910         if (!Printer) {
6911                 return WERR_BADFID;
6912         }
6913
6914         if (!get_printer_snum(p, handle, &snum, NULL)) {
6915                 return WERR_BADFID;
6916         }
6917
6918         /* Check calling user has permission to update printer description */
6919         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6920                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6921                 return WERR_ACCESS_DENIED;
6922         }
6923
6924         return winreg_update_printer_internal(p->mem_ctx,
6925                                      get_session_info_system(),
6926                                      p->msg_ctx,
6927                                      lp_const_servicename(snum),
6928                                      info2_mask,
6929                                      NULL,
6930                                      devmode,
6931                                      NULL);
6932 }
6933
6934
6935 /****************************************************************
6936  _spoolss_SetPrinter
6937 ****************************************************************/
6938
6939 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6940                            struct spoolss_SetPrinter *r)
6941 {
6942         WERROR result;
6943
6944         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6945
6946         if (!Printer) {
6947                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6948                         OUR_HANDLE(r->in.handle)));
6949                 return WERR_BADFID;
6950         }
6951
6952         /* check the level */
6953         switch (r->in.info_ctr->level) {
6954                 case 0:
6955                         return control_printer(r->in.handle, r->in.command, p);
6956                 case 2:
6957                         result = update_printer(p, r->in.handle,
6958                                                 r->in.info_ctr,
6959                                                 r->in.devmode_ctr->devmode);
6960                         if (!W_ERROR_IS_OK(result))
6961                                 return result;
6962                         if (r->in.secdesc_ctr->sd)
6963                                 result = update_printer_sec(r->in.handle, p,
6964                                                             r->in.secdesc_ctr);
6965                         return result;
6966                 case 3:
6967                         return update_printer_sec(r->in.handle, p,
6968                                                   r->in.secdesc_ctr);
6969                 case 7:
6970                         return publish_or_unpublish_printer(p, r->in.handle,
6971                                                             r->in.info_ctr->info.info7);
6972                 case 8:
6973                         return update_printer_devmode(p, r->in.handle,
6974                                                       r->in.devmode_ctr->devmode);
6975                 default:
6976                         return WERR_UNKNOWN_LEVEL;
6977         }
6978 }
6979
6980 /****************************************************************
6981  _spoolss_FindClosePrinterNotify
6982 ****************************************************************/
6983
6984 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6985                                        struct spoolss_FindClosePrinterNotify *r)
6986 {
6987         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6988
6989         if (!Printer) {
6990                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6991                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6992                 return WERR_BADFID;
6993         }
6994
6995         if (Printer->notify.cli_chan != NULL &&
6996             Printer->notify.cli_chan->active_connections > 0) {
6997                 int snum = -1;
6998
6999                 if (Printer->printer_type == SPLHND_PRINTER) {
7000                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7001                                 return WERR_BADFID;
7002                         }
7003                 }
7004
7005                 srv_spoolss_replycloseprinter(snum, Printer);
7006         }
7007
7008         Printer->notify.flags=0;
7009         Printer->notify.options=0;
7010         Printer->notify.localmachine[0]='\0';
7011         Printer->notify.printerlocal=0;
7012         TALLOC_FREE(Printer->notify.option);
7013
7014         return WERR_OK;
7015 }
7016
7017 /****************************************************************
7018  _spoolss_AddJob
7019 ****************************************************************/
7020
7021 WERROR _spoolss_AddJob(struct pipes_struct *p,
7022                        struct spoolss_AddJob *r)
7023 {
7024         if (!r->in.buffer && (r->in.offered != 0)) {
7025                 return WERR_INVALID_PARAM;
7026         }
7027
7028         /* this is what a NT server returns for AddJob. AddJob must fail on
7029          * non-local printers */
7030
7031         if (r->in.level != 1) {
7032                 return WERR_UNKNOWN_LEVEL;
7033         }
7034
7035         return WERR_INVALID_PARAM;
7036 }
7037
7038 /****************************************************************************
7039 fill_job_info1
7040 ****************************************************************************/
7041
7042 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7043                              struct spoolss_JobInfo1 *r,
7044                              const print_queue_struct *queue,
7045                              uint32_t jobid,
7046                              int position, int snum,
7047                              struct spoolss_PrinterInfo2 *pinfo2)
7048 {
7049         struct tm *t;
7050
7051         t = gmtime(&queue->time);
7052
7053         r->job_id               = jobid;
7054
7055         r->printer_name         = lp_servicename(mem_ctx, snum);
7056         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7057         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7058         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7059         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7060         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7061         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7062         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7063         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7064         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7065         r->text_status          = talloc_strdup(mem_ctx, "");
7066         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7067
7068         r->status               = nt_printj_status(queue->status);
7069         r->priority             = queue->priority;
7070         r->position             = position;
7071         r->total_pages          = queue->page_count;
7072         r->pages_printed        = 0; /* ??? */
7073
7074         init_systemtime(&r->submitted, t);
7075
7076         return WERR_OK;
7077 }
7078
7079 /****************************************************************************
7080 fill_job_info2
7081 ****************************************************************************/
7082
7083 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7084                              struct spoolss_JobInfo2 *r,
7085                              const print_queue_struct *queue,
7086                              int position, int snum,
7087                              struct spoolss_PrinterInfo2 *pinfo2,
7088                              struct spoolss_DeviceMode *devmode)
7089 {
7090         struct tm *t;
7091
7092         t = gmtime(&queue->time);
7093
7094         r->job_id               = queue->sysjob;
7095
7096         r->printer_name         = lp_servicename(mem_ctx, snum);
7097         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7098         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7099         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7100         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7101         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7102         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7103         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7104         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7105         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7106         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7107         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7108         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7109         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7110         r->parameters           = talloc_strdup(mem_ctx, "");
7111         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7112         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7113         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7114
7115         r->devmode              = devmode;
7116
7117         r->text_status          = talloc_strdup(mem_ctx, "");
7118         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7119
7120         r->secdesc              = NULL;
7121
7122         r->status               = nt_printj_status(queue->status);
7123         r->priority             = queue->priority;
7124         r->position             = position;
7125         r->start_time           = 0;
7126         r->until_time           = 0;
7127         r->total_pages          = queue->page_count;
7128         r->size                 = queue->size;
7129         init_systemtime(&r->submitted, t);
7130         r->time                 = 0;
7131         r->pages_printed        = 0; /* ??? */
7132
7133         return WERR_OK;
7134 }
7135
7136 /****************************************************************************
7137 fill_job_info3
7138 ****************************************************************************/
7139
7140 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7141                              struct spoolss_JobInfo3 *r,
7142                              const print_queue_struct *queue,
7143                              const print_queue_struct *next_queue,
7144                              int position, int snum,
7145                              struct spoolss_PrinterInfo2 *pinfo2)
7146 {
7147         r->job_id               = queue->sysjob;
7148         r->next_job_id          = 0;
7149         if (next_queue) {
7150                 r->next_job_id  = next_queue->sysjob;
7151         }
7152         r->reserved             = 0;
7153
7154         return WERR_OK;
7155 }
7156
7157 /****************************************************************************
7158  Enumjobs at level 1.
7159 ****************************************************************************/
7160
7161 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7162                               const print_queue_struct *queue,
7163                               uint32_t num_queues, int snum,
7164                               struct spoolss_PrinterInfo2 *pinfo2,
7165                               union spoolss_JobInfo **info_p,
7166                               uint32_t *count)
7167 {
7168         union spoolss_JobInfo *info;
7169         int i;
7170         WERROR result = WERR_OK;
7171         uint32_t num_filled;
7172         struct tdb_print_db *pdb;
7173
7174         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7175         if (info == NULL) {
7176                 result = WERR_NOMEM;
7177                 goto err_out;
7178         }
7179
7180         pdb = get_print_db_byname(pinfo2->sharename);
7181         if (pdb == NULL) {
7182                 result = WERR_INVALID_PARAM;
7183                 goto err_info_free;
7184         }
7185
7186         num_filled = 0;
7187         for (i = 0; i < num_queues; i++) {
7188                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7189                 if (jobid == (uint32_t)-1) {
7190                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7191                         continue;
7192                 }
7193
7194                 result = fill_job_info1(info,
7195                                         &info[num_filled].info1,
7196                                         &queue[i],
7197                                         jobid,
7198                                         i,
7199                                         snum,
7200                                         pinfo2);
7201                 if (!W_ERROR_IS_OK(result)) {
7202                         goto err_pdb_drop;
7203                 }
7204
7205                 num_filled++;
7206         }
7207
7208         release_print_db(pdb);
7209         *info_p = info;
7210         *count = num_filled;
7211
7212         return WERR_OK;
7213
7214 err_pdb_drop:
7215         release_print_db(pdb);
7216 err_info_free:
7217         TALLOC_FREE(info);
7218 err_out:
7219         *count = 0;
7220         return result;
7221 }
7222
7223 /****************************************************************************
7224  Enumjobs at level 2.
7225 ****************************************************************************/
7226
7227 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7228                               const print_queue_struct *queue,
7229                               uint32_t num_queues, int snum,
7230                               struct spoolss_PrinterInfo2 *pinfo2,
7231                               union spoolss_JobInfo **info_p,
7232                               uint32_t *count)
7233 {
7234         union spoolss_JobInfo *info;
7235         int i;
7236         WERROR result = WERR_OK;
7237
7238         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7239         W_ERROR_HAVE_NO_MEMORY(info);
7240
7241         *count = num_queues;
7242
7243         for (i=0; i<*count; i++) {
7244                 struct spoolss_DeviceMode *devmode;
7245
7246                 result = spoolss_create_default_devmode(info,
7247                                                         pinfo2->printername,
7248                                                         &devmode);
7249                 if (!W_ERROR_IS_OK(result)) {
7250                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7251                         goto out;
7252                 }
7253
7254                 result = fill_job_info2(info,
7255                                         &info[i].info2,
7256                                         &queue[i],
7257                                         i,
7258                                         snum,
7259                                         pinfo2,
7260                                         devmode);
7261                 if (!W_ERROR_IS_OK(result)) {
7262                         goto out;
7263                 }
7264         }
7265
7266  out:
7267         if (!W_ERROR_IS_OK(result)) {
7268                 TALLOC_FREE(info);
7269                 *count = 0;
7270                 return result;
7271         }
7272
7273         *info_p = info;
7274
7275         return WERR_OK;
7276 }
7277
7278 /****************************************************************************
7279  Enumjobs at level 3.
7280 ****************************************************************************/
7281
7282 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7283                               const print_queue_struct *queue,
7284                               uint32_t num_queues, int snum,
7285                               struct spoolss_PrinterInfo2 *pinfo2,
7286                               union spoolss_JobInfo **info_p,
7287                               uint32_t *count)
7288 {
7289         union spoolss_JobInfo *info;
7290         int i;
7291         WERROR result = WERR_OK;
7292
7293         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7294         W_ERROR_HAVE_NO_MEMORY(info);
7295
7296         *count = num_queues;
7297
7298         for (i=0; i<*count; i++) {
7299                 const print_queue_struct *next_queue = NULL;
7300
7301                 if (i+1 < *count) {
7302                         next_queue = &queue[i+1];
7303                 }
7304
7305                 result = fill_job_info3(info,
7306                                         &info[i].info3,
7307                                         &queue[i],
7308                                         next_queue,
7309                                         i,
7310                                         snum,
7311                                         pinfo2);
7312                 if (!W_ERROR_IS_OK(result)) {
7313                         goto out;
7314                 }
7315         }
7316
7317  out:
7318         if (!W_ERROR_IS_OK(result)) {
7319                 TALLOC_FREE(info);
7320                 *count = 0;
7321                 return result;
7322         }
7323
7324         *info_p = info;
7325
7326         return WERR_OK;
7327 }
7328
7329 /****************************************************************
7330  _spoolss_EnumJobs
7331 ****************************************************************/
7332
7333 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7334                          struct spoolss_EnumJobs *r)
7335 {
7336         WERROR result;
7337         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7338         int snum;
7339         print_status_struct prt_status;
7340         print_queue_struct *queue = NULL;
7341         uint32_t count;
7342
7343         /* that's an [in out] buffer */
7344
7345         if (!r->in.buffer && (r->in.offered != 0)) {
7346                 return WERR_INVALID_PARAM;
7347         }
7348
7349         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7350                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7351                 return WERR_UNKNOWN_LEVEL;
7352         }
7353
7354         DEBUG(4,("_spoolss_EnumJobs\n"));
7355
7356         *r->out.needed = 0;
7357         *r->out.count = 0;
7358         *r->out.info = NULL;
7359
7360         /* lookup the printer snum and tdb entry */
7361
7362         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7363                 return WERR_BADFID;
7364         }
7365
7366         result = winreg_get_printer_internal(p->mem_ctx,
7367                                     get_session_info_system(),
7368                                     p->msg_ctx,
7369                                     lp_const_servicename(snum),
7370                                     &pinfo2);
7371         if (!W_ERROR_IS_OK(result)) {
7372                 return result;
7373         }
7374
7375         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7376         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7377                 count, prt_status.status, prt_status.message));
7378
7379         if (count == 0) {
7380                 SAFE_FREE(queue);
7381                 TALLOC_FREE(pinfo2);
7382                 return WERR_OK;
7383         }
7384
7385         switch (r->in.level) {
7386         case 1:
7387                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7388                                          pinfo2, r->out.info, r->out.count);
7389                 break;
7390         case 2:
7391                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7392                                          pinfo2, r->out.info, r->out.count);
7393                 break;
7394         case 3:
7395                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7396                                          pinfo2, r->out.info, r->out.count);
7397                 break;
7398         default:
7399                 SMB_ASSERT(false);      /* level checked on entry */
7400                 break;
7401         }
7402
7403         SAFE_FREE(queue);
7404         TALLOC_FREE(pinfo2);
7405
7406         if (!W_ERROR_IS_OK(result)) {
7407                 return result;
7408         }
7409
7410         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7411                                                      spoolss_EnumJobs,
7412                                                      *r->out.info, r->in.level,
7413                                                      *r->out.count);
7414         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7415         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7416
7417         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7418 }
7419
7420 /****************************************************************
7421  _spoolss_ScheduleJob
7422 ****************************************************************/
7423
7424 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7425                             struct spoolss_ScheduleJob *r)
7426 {
7427         return WERR_OK;
7428 }
7429
7430 /****************************************************************
7431 ****************************************************************/
7432
7433 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7434                                struct messaging_context *msg_ctx,
7435                                const char *printer_name,
7436                                uint32_t job_id,
7437                                struct spoolss_SetJobInfo1 *r)
7438 {
7439         char *old_doc_name;
7440
7441         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7442                 return WERR_BADFID;
7443         }
7444
7445         if (strequal(old_doc_name, r->document_name)) {
7446                 return WERR_OK;
7447         }
7448
7449         if (!print_job_set_name(server_event_context(), msg_ctx,
7450                                 printer_name, job_id, r->document_name)) {
7451                 return WERR_BADFID;
7452         }
7453
7454         return WERR_OK;
7455 }
7456
7457 /****************************************************************
7458  _spoolss_SetJob
7459 ****************************************************************/
7460
7461 WERROR _spoolss_SetJob(struct pipes_struct *p,
7462                        struct spoolss_SetJob *r)
7463 {
7464         const struct auth_session_info *session_info = p->session_info;
7465         int snum;
7466         WERROR errcode = WERR_BADFUNC;
7467
7468         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7469                 return WERR_BADFID;
7470         }
7471
7472         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7473                 return WERR_INVALID_PRINTER_NAME;
7474         }
7475
7476         switch (r->in.command) {
7477         case SPOOLSS_JOB_CONTROL_CANCEL:
7478         case SPOOLSS_JOB_CONTROL_DELETE:
7479                 errcode = print_job_delete(session_info, p->msg_ctx,
7480                                            snum, r->in.job_id);
7481                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7482                         errcode = WERR_OK;
7483                 }
7484                 break;
7485         case SPOOLSS_JOB_CONTROL_PAUSE:
7486                 errcode = print_job_pause(session_info, p->msg_ctx,
7487                                           snum, r->in.job_id);
7488                 break;
7489         case SPOOLSS_JOB_CONTROL_RESTART:
7490         case SPOOLSS_JOB_CONTROL_RESUME:
7491                 errcode = print_job_resume(session_info, p->msg_ctx,
7492                                            snum, r->in.job_id);
7493                 break;
7494         case 0:
7495                 errcode = WERR_OK;
7496                 break;
7497         default:
7498                 return WERR_UNKNOWN_LEVEL;
7499         }
7500
7501         if (!W_ERROR_IS_OK(errcode)) {
7502                 return errcode;
7503         }
7504
7505         if (r->in.ctr == NULL) {
7506                 return errcode;
7507         }
7508
7509         switch (r->in.ctr->level) {
7510         case 1:
7511                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7512                                            lp_const_servicename(snum),
7513                                            r->in.job_id,
7514                                            r->in.ctr->info.info1);
7515                 break;
7516         case 2:
7517         case 3:
7518         case 4:
7519         default:
7520                 return WERR_UNKNOWN_LEVEL;
7521         }
7522
7523         return errcode;
7524 }
7525
7526 /****************************************************************************
7527  Enumerates all printer drivers by level and architecture.
7528 ****************************************************************************/
7529
7530 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7531                                                        const struct auth_session_info *session_info,
7532                                                        struct messaging_context *msg_ctx,
7533                                                        const char *servername,
7534                                                        const char *architecture,
7535                                                        uint32_t level,
7536                                                        union spoolss_DriverInfo **info_p,
7537                                                        uint32_t *count_p)
7538 {
7539         int i;
7540         uint32_t version;
7541         struct spoolss_DriverInfo8 *driver;
7542         union spoolss_DriverInfo *info = NULL;
7543         uint32_t count = 0;
7544         WERROR result = WERR_OK;
7545         uint32_t num_drivers;
7546         const char **drivers;
7547         struct dcerpc_binding_handle *b;
7548         TALLOC_CTX *tmp_ctx = NULL;
7549
7550         *count_p = 0;
7551         *info_p = NULL;
7552
7553         tmp_ctx = talloc_new(mem_ctx);
7554         if (!tmp_ctx) {
7555                 return WERR_NOMEM;
7556         }
7557
7558         result = winreg_printer_binding_handle(tmp_ctx,
7559                                                session_info,
7560                                                msg_ctx,
7561                                                &b);
7562         if (!W_ERROR_IS_OK(result)) {
7563                 goto out;
7564         }
7565
7566         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7567                 result = winreg_get_driver_list(tmp_ctx, b,
7568                                                 architecture, version,
7569                                                 &num_drivers, &drivers);
7570                 if (!W_ERROR_IS_OK(result)) {
7571                         goto out;
7572                 }
7573                 DEBUG(4, ("we have:[%d] drivers in environment"
7574                           " [%s] and version [%d]\n",
7575                           num_drivers, architecture, version));
7576
7577                 if (num_drivers != 0) {
7578                         info = talloc_realloc(tmp_ctx, info,
7579                                                     union spoolss_DriverInfo,
7580                                                     count + num_drivers);
7581                         if (!info) {
7582                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7583                                         "failed to enlarge driver info buffer!\n"));
7584                                 result = WERR_NOMEM;
7585                                 goto out;
7586                         }
7587                 }
7588
7589                 for (i = 0; i < num_drivers; i++) {
7590                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7591
7592                         result = winreg_get_driver(tmp_ctx, b,
7593                                                    architecture, drivers[i],
7594                                                    version, &driver);
7595                         if (!W_ERROR_IS_OK(result)) {
7596                                 goto out;
7597                         }
7598
7599                         switch (level) {
7600                         case 1:
7601                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7602                                                                    driver, servername);
7603                                 break;
7604                         case 2:
7605                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7606                                                                    driver, servername);
7607                                 break;
7608                         case 3:
7609                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7610                                                                    driver, servername);
7611                                 break;
7612                         case 4:
7613                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7614                                                                    driver, servername);
7615                                 break;
7616                         case 5:
7617                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7618                                                                    driver, servername);
7619                                 break;
7620                         case 6:
7621                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7622                                                                    driver, servername);
7623                                 break;
7624                         case 8:
7625                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7626                                                                    driver, servername);
7627                                 break;
7628                         default:
7629                                 result = WERR_UNKNOWN_LEVEL;
7630                                 break;
7631                         }
7632
7633                         TALLOC_FREE(driver);
7634
7635                         if (!W_ERROR_IS_OK(result)) {
7636                                 goto out;
7637                         }
7638                 }
7639
7640                 count += num_drivers;
7641                 TALLOC_FREE(drivers);
7642         }
7643
7644 out:
7645         if (W_ERROR_IS_OK(result)) {
7646                 *info_p = talloc_move(mem_ctx, &info);
7647                 *count_p = count;
7648         }
7649
7650         talloc_free(tmp_ctx);
7651         return result;
7652 }
7653
7654 /****************************************************************************
7655  Enumerates all printer drivers by level.
7656 ****************************************************************************/
7657
7658 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7659                                        const struct auth_session_info *session_info,
7660                                        struct messaging_context *msg_ctx,
7661                                        const char *servername,
7662                                        const char *architecture,
7663                                        uint32_t level,
7664                                        union spoolss_DriverInfo **info_p,
7665                                        uint32_t *count_p)
7666 {
7667         uint32_t a,i;
7668         WERROR result = WERR_OK;
7669
7670         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7671
7672                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7673
7674                         union spoolss_DriverInfo *info = NULL;
7675                         uint32_t count = 0;
7676
7677                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7678                                                                           session_info,
7679                                                                           msg_ctx,
7680                                                                           servername,
7681                                                                           archi_table[a].long_archi,
7682                                                                           level,
7683                                                                           &info,
7684                                                                           &count);
7685                         if (!W_ERROR_IS_OK(result)) {
7686                                 continue;
7687                         }
7688
7689                         for (i=0; i < count; i++) {
7690                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7691                                              info[i], info_p, count_p);
7692                         }
7693                 }
7694
7695                 return result;
7696         }
7697
7698         return enumprinterdrivers_level_by_architecture(mem_ctx,
7699                                                         session_info,
7700                                                         msg_ctx,
7701                                                         servername,
7702                                                         architecture,
7703                                                         level,
7704                                                         info_p,
7705                                                         count_p);
7706 }
7707
7708 /****************************************************************
7709  _spoolss_EnumPrinterDrivers
7710 ****************************************************************/
7711
7712 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7713                                    struct spoolss_EnumPrinterDrivers *r)
7714 {
7715         const char *cservername;
7716         WERROR result;
7717
7718         /* that's an [in out] buffer */
7719
7720         if (!r->in.buffer && (r->in.offered != 0)) {
7721                 return WERR_INVALID_PARAM;
7722         }
7723
7724         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7725
7726         *r->out.needed = 0;
7727         *r->out.count = 0;
7728         *r->out.info = NULL;
7729
7730         cservername = canon_servername(r->in.server);
7731
7732         if (!is_myname_or_ipaddr(cservername)) {
7733                 return WERR_UNKNOWN_PRINTER_DRIVER;
7734         }
7735
7736         result = enumprinterdrivers_level(p->mem_ctx,
7737                                           get_session_info_system(),
7738                                           p->msg_ctx,
7739                                           cservername,
7740                                           r->in.environment,
7741                                           r->in.level,
7742                                           r->out.info,
7743                                           r->out.count);
7744         if (!W_ERROR_IS_OK(result)) {
7745                 return result;
7746         }
7747
7748         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7749                                                      spoolss_EnumPrinterDrivers,
7750                                                      *r->out.info, r->in.level,
7751                                                      *r->out.count);
7752         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7753         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7754
7755         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7756 }
7757
7758 /****************************************************************
7759  _spoolss_EnumForms
7760 ****************************************************************/
7761
7762 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7763                           struct spoolss_EnumForms *r)
7764 {
7765         WERROR result;
7766
7767         *r->out.count = 0;
7768         *r->out.needed = 0;
7769         *r->out.info = NULL;
7770
7771         /* that's an [in out] buffer */
7772
7773         if (!r->in.buffer && (r->in.offered != 0) ) {
7774                 return WERR_INVALID_PARAM;
7775         }
7776
7777         DEBUG(4,("_spoolss_EnumForms\n"));
7778         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7779         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7780
7781         switch (r->in.level) {
7782         case 1:
7783                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7784                                                    get_session_info_system(),
7785                                                    p->msg_ctx,
7786                                                    r->out.count,
7787                                                    r->out.info);
7788                 break;
7789         default:
7790                 result = WERR_UNKNOWN_LEVEL;
7791                 break;
7792         }
7793
7794         if (!W_ERROR_IS_OK(result)) {
7795                 return result;
7796         }
7797
7798         if (*r->out.count == 0) {
7799                 return WERR_NO_MORE_ITEMS;
7800         }
7801
7802         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7803                                                      spoolss_EnumForms,
7804                                                      *r->out.info, r->in.level,
7805                                                      *r->out.count);
7806         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7807         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7808
7809         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7810 }
7811
7812 /****************************************************************
7813  _spoolss_GetForm
7814 ****************************************************************/
7815
7816 WERROR _spoolss_GetForm(struct pipes_struct *p,
7817                         struct spoolss_GetForm *r)
7818 {
7819         WERROR result;
7820
7821         /* that's an [in out] buffer */
7822
7823         if (!r->in.buffer && (r->in.offered != 0)) {
7824                 return WERR_INVALID_PARAM;
7825         }
7826
7827         DEBUG(4,("_spoolss_GetForm\n"));
7828         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7829         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7830
7831         switch (r->in.level) {
7832         case 1:
7833                 result = winreg_printer_getform1_internal(p->mem_ctx,
7834                                                  get_session_info_system(),
7835                                                  p->msg_ctx,
7836                                                  r->in.form_name,
7837                                                  &r->out.info->info1);
7838                 break;
7839         default:
7840                 result = WERR_UNKNOWN_LEVEL;
7841                 break;
7842         }
7843
7844         if (!W_ERROR_IS_OK(result)) {
7845                 TALLOC_FREE(r->out.info);
7846                 return result;
7847         }
7848
7849         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7850                                                r->out.info, r->in.level);
7851         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7852
7853         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7854 }
7855
7856 /****************************************************************************
7857 ****************************************************************************/
7858
7859 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7860                           struct spoolss_PortInfo1 *r,
7861                           const char *name)
7862 {
7863         r->port_name = talloc_strdup(mem_ctx, name);
7864         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7865
7866         return WERR_OK;
7867 }
7868
7869 /****************************************************************************
7870  TODO: This probably needs distinguish between TCP/IP and Local ports
7871  somehow.
7872 ****************************************************************************/
7873
7874 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7875                           struct spoolss_PortInfo2 *r,
7876                           const char *name)
7877 {
7878         r->port_name = talloc_strdup(mem_ctx, name);
7879         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7880
7881         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7882         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7883
7884         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7885         W_ERROR_HAVE_NO_MEMORY(r->description);
7886
7887         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7888         r->reserved = 0;
7889
7890         return WERR_OK;
7891 }
7892
7893
7894 /****************************************************************************
7895  wrapper around the enumer ports command
7896 ****************************************************************************/
7897
7898 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7899 {
7900         char *cmd = lp_enumports_cmd(talloc_tos());
7901         char **qlines = NULL;
7902         char *command = NULL;
7903         int numlines;
7904         int ret;
7905         int fd;
7906
7907         *count = 0;
7908         *lines = NULL;
7909
7910         /* if no hook then just fill in the default port */
7911
7912         if ( !*cmd ) {
7913                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7914                         return WERR_NOMEM;
7915                 }
7916                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7917                         TALLOC_FREE(qlines);
7918                         return WERR_NOMEM;
7919                 }
7920                 qlines[1] = NULL;
7921                 numlines = 1;
7922         }
7923         else {
7924                 /* we have a valid enumport command */
7925
7926                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7927                 if (!command) {
7928                         return WERR_NOMEM;
7929                 }
7930
7931                 DEBUG(10,("Running [%s]\n", command));
7932                 ret = smbrun(command, &fd);
7933                 DEBUG(10,("Returned [%d]\n", ret));
7934                 TALLOC_FREE(command);
7935                 if (ret != 0) {
7936                         if (fd != -1) {
7937                                 close(fd);
7938                         }
7939                         return WERR_ACCESS_DENIED;
7940                 }
7941
7942                 numlines = 0;
7943                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7944                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7945                 close(fd);
7946         }
7947
7948         *count = numlines;
7949         *lines = qlines;
7950
7951         return WERR_OK;
7952 }
7953
7954 /****************************************************************************
7955  enumports level 1.
7956 ****************************************************************************/
7957
7958 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7959                                 union spoolss_PortInfo **info_p,
7960                                 uint32_t *count)
7961 {
7962         union spoolss_PortInfo *info = NULL;
7963         int i=0;
7964         WERROR result = WERR_OK;
7965         char **qlines = NULL;
7966         int numlines = 0;
7967
7968         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7969         if (!W_ERROR_IS_OK(result)) {
7970                 goto out;
7971         }
7972
7973         if (numlines) {
7974                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7975                 if (!info) {
7976                         DEBUG(10,("Returning WERR_NOMEM\n"));
7977                         result = WERR_NOMEM;
7978                         goto out;
7979                 }
7980
7981                 for (i=0; i<numlines; i++) {
7982                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7983                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7984                         if (!W_ERROR_IS_OK(result)) {
7985                                 goto out;
7986                         }
7987                 }
7988         }
7989         TALLOC_FREE(qlines);
7990
7991 out:
7992         if (!W_ERROR_IS_OK(result)) {
7993                 TALLOC_FREE(info);
7994                 TALLOC_FREE(qlines);
7995                 *count = 0;
7996                 *info_p = NULL;
7997                 return result;
7998         }
7999
8000         *info_p = info;
8001         *count = numlines;
8002
8003         return WERR_OK;
8004 }
8005
8006 /****************************************************************************
8007  enumports level 2.
8008 ****************************************************************************/
8009
8010 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8011                                 union spoolss_PortInfo **info_p,
8012                                 uint32_t *count)
8013 {
8014         union spoolss_PortInfo *info = NULL;
8015         int i=0;
8016         WERROR result = WERR_OK;
8017         char **qlines = NULL;
8018         int numlines = 0;
8019
8020         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8021         if (!W_ERROR_IS_OK(result)) {
8022                 goto out;
8023         }
8024
8025         if (numlines) {
8026                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8027                 if (!info) {
8028                         DEBUG(10,("Returning WERR_NOMEM\n"));
8029                         result = WERR_NOMEM;
8030                         goto out;
8031                 }
8032
8033                 for (i=0; i<numlines; i++) {
8034                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8035                         result = fill_port_2(info, &info[i].info2, qlines[i]);
8036                         if (!W_ERROR_IS_OK(result)) {
8037                                 goto out;
8038                         }
8039                 }
8040         }
8041         TALLOC_FREE(qlines);
8042
8043 out:
8044         if (!W_ERROR_IS_OK(result)) {
8045                 TALLOC_FREE(info);
8046                 TALLOC_FREE(qlines);
8047                 *count = 0;
8048                 *info_p = NULL;
8049                 return result;
8050         }
8051
8052         *info_p = info;
8053         *count = numlines;
8054
8055         return WERR_OK;
8056 }
8057
8058 /****************************************************************
8059  _spoolss_EnumPorts
8060 ****************************************************************/
8061
8062 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8063                           struct spoolss_EnumPorts *r)
8064 {
8065         WERROR result;
8066
8067         /* that's an [in out] buffer */
8068
8069         if (!r->in.buffer && (r->in.offered != 0)) {
8070                 return WERR_INVALID_PARAM;
8071         }
8072
8073         DEBUG(4,("_spoolss_EnumPorts\n"));
8074
8075         *r->out.count = 0;
8076         *r->out.needed = 0;
8077         *r->out.info = NULL;
8078
8079         switch (r->in.level) {
8080         case 1:
8081                 result = enumports_level_1(p->mem_ctx, r->out.info,
8082                                            r->out.count);
8083                 break;
8084         case 2:
8085                 result = enumports_level_2(p->mem_ctx, r->out.info,
8086                                            r->out.count);
8087                 break;
8088         default:
8089                 return WERR_UNKNOWN_LEVEL;
8090         }
8091
8092         if (!W_ERROR_IS_OK(result)) {
8093                 return result;
8094         }
8095
8096         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8097                                                      spoolss_EnumPorts,
8098                                                      *r->out.info, r->in.level,
8099                                                      *r->out.count);
8100         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8101         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8102
8103         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8104 }
8105
8106 /****************************************************************************
8107 ****************************************************************************/
8108
8109 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8110                                            const char *server,
8111                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8112                                            struct spoolss_DeviceMode *devmode,
8113                                            struct security_descriptor *secdesc,
8114                                            struct spoolss_UserLevelCtr *user_ctr,
8115                                            struct policy_handle *handle)
8116 {
8117         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8118         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8119         int     snum;
8120         WERROR err = WERR_OK;
8121
8122         /* samba does not have a concept of local, non-shared printers yet, so
8123          * make sure we always setup sharename - gd */
8124         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8125             (info2->printername != NULL && info2->printername[0] != '\0')) {
8126                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8127                         "no sharename has been set, setting printername %s as sharename\n",
8128                         info2->printername));
8129                 info2->sharename = info2->printername;
8130         }
8131
8132         /* check to see if the printer already exists */
8133         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8134                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8135                         info2->sharename));
8136                 return WERR_PRINTER_ALREADY_EXISTS;
8137         }
8138
8139         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8140                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8141                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8142                                 info2->printername));
8143                         return WERR_PRINTER_ALREADY_EXISTS;
8144                 }
8145         }
8146
8147         /* validate printer info struct */
8148         if (!info2->printername || strlen(info2->printername) == 0) {
8149                 return WERR_INVALID_PRINTER_NAME;
8150         }
8151         if (!info2->portname || strlen(info2->portname) == 0) {
8152                 return WERR_UNKNOWN_PORT;
8153         }
8154         if (!info2->drivername || strlen(info2->drivername) == 0) {
8155                 return WERR_UNKNOWN_PRINTER_DRIVER;
8156         }
8157         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8158                 return WERR_UNKNOWN_PRINTPROCESSOR;
8159         }
8160
8161         /* FIXME!!!  smbd should check to see if the driver is installed before
8162            trying to add a printer like this  --jerry */
8163
8164         if (*lp_addprinter_cmd(talloc_tos()) ) {
8165                 char *raddr;
8166
8167                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8168                                                          p->mem_ctx);
8169                 if (raddr == NULL) {
8170                         return WERR_NOMEM;
8171                 }
8172
8173                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8174                                        info2, raddr,
8175                                        p->msg_ctx) ) {
8176                         return WERR_ACCESS_DENIED;
8177                 }
8178         } else {
8179                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8180                         "smb.conf parameter \"addprinter command\" is defined. This "
8181                         "parameter must exist for this call to succeed\n",
8182                         info2->sharename ));
8183         }
8184
8185         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8186                 return WERR_ACCESS_DENIED;
8187         }
8188
8189         /* you must be a printer admin to add a new printer */
8190         if (!print_access_check(p->session_info,
8191                                 p->msg_ctx,
8192                                 snum,
8193                                 PRINTER_ACCESS_ADMINISTER)) {
8194                 return WERR_ACCESS_DENIED;
8195         }
8196
8197         /*
8198          * Do sanity check on the requested changes for Samba.
8199          */
8200
8201         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8202                 return WERR_INVALID_PARAM;
8203         }
8204
8205         if (devmode == NULL) {
8206                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8207         }
8208
8209         err = update_dsspooler(p->mem_ctx,
8210                                get_session_info_system(),
8211                                p->msg_ctx,
8212                                0,
8213                                info2,
8214                                NULL);
8215         if (!W_ERROR_IS_OK(err)) {
8216                 return err;
8217         }
8218
8219         err = winreg_update_printer_internal(p->mem_ctx,
8220                                     get_session_info_system(),
8221                                     p->msg_ctx,
8222                                     info2->sharename,
8223                                     info2_mask,
8224                                     info2,
8225                                     devmode,
8226                                     secdesc);
8227         if (!W_ERROR_IS_OK(err)) {
8228                 return err;
8229         }
8230
8231         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8232         if (!W_ERROR_IS_OK(err)) {
8233                 /* Handle open failed - remove addition. */
8234                 ZERO_STRUCTP(handle);
8235                 return err;
8236         }
8237
8238         return WERR_OK;
8239 }
8240
8241 /****************************************************************
8242  _spoolss_AddPrinterEx
8243 ****************************************************************/
8244
8245 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8246                              struct spoolss_AddPrinterEx *r)
8247 {
8248         switch (r->in.info_ctr->level) {
8249         case 1:
8250                 /* we don't handle yet */
8251                 /* but I know what to do ... */
8252                 return WERR_UNKNOWN_LEVEL;
8253         case 2:
8254                 return spoolss_addprinterex_level_2(p, r->in.server,
8255                                                     r->in.info_ctr,
8256                                                     r->in.devmode_ctr->devmode,
8257                                                     r->in.secdesc_ctr->sd,
8258                                                     r->in.userlevel_ctr,
8259                                                     r->out.handle);
8260         default:
8261                 return WERR_UNKNOWN_LEVEL;
8262         }
8263 }
8264
8265 /****************************************************************
8266  _spoolss_AddPrinter
8267 ****************************************************************/
8268
8269 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8270                            struct spoolss_AddPrinter *r)
8271 {
8272         struct spoolss_AddPrinterEx a;
8273         struct spoolss_UserLevelCtr userlevel_ctr;
8274
8275         ZERO_STRUCT(userlevel_ctr);
8276
8277         userlevel_ctr.level = 1;
8278
8279         a.in.server             = r->in.server;
8280         a.in.info_ctr           = r->in.info_ctr;
8281         a.in.devmode_ctr        = r->in.devmode_ctr;
8282         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8283         a.in.userlevel_ctr      = &userlevel_ctr;
8284         a.out.handle            = r->out.handle;
8285
8286         return _spoolss_AddPrinterEx(p, &a);
8287 }
8288
8289 /****************************************************************
8290  _spoolss_AddPrinterDriverEx
8291 ****************************************************************/
8292
8293 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8294                                    struct spoolss_AddPrinterDriverEx *r)
8295 {
8296         WERROR err = WERR_OK;
8297         const char *driver_name = NULL;
8298         uint32_t version;
8299         const char *fn;
8300
8301         switch (p->opnum) {
8302                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8303                         fn = "_spoolss_AddPrinterDriver";
8304                         break;
8305                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8306                         fn = "_spoolss_AddPrinterDriverEx";
8307                         break;
8308                 default:
8309                         return WERR_INVALID_PARAM;
8310         }
8311
8312         /*
8313          * we only support the semantics of AddPrinterDriver()
8314          * i.e. only copy files that are newer than existing ones
8315          */
8316
8317         if (r->in.flags == 0) {
8318                 return WERR_INVALID_PARAM;
8319         }
8320
8321         if (r->in.flags != APD_COPY_NEW_FILES) {
8322                 return WERR_ACCESS_DENIED;
8323         }
8324
8325         /* FIXME */
8326         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8327                 /* Clever hack from Martin Zielinski <mz@seh.de>
8328                  * to allow downgrade from level 8 (Vista).
8329                  */
8330                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8331                         r->in.info_ctr->level));
8332                 return WERR_UNKNOWN_LEVEL;
8333         }
8334
8335         DEBUG(5,("Cleaning driver's information\n"));
8336         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8337         if (!W_ERROR_IS_OK(err))
8338                 goto done;
8339
8340         DEBUG(5,("Moving driver to final destination\n"));
8341         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8342         if (!W_ERROR_IS_OK(err)) {
8343                 goto done;
8344         }
8345
8346         err = winreg_add_driver_internal(p->mem_ctx,
8347                                 get_session_info_system(),
8348                                 p->msg_ctx,
8349                                 r->in.info_ctr,
8350                                 &driver_name,
8351                                 &version);
8352         if (!W_ERROR_IS_OK(err)) {
8353                 goto done;
8354         }
8355
8356         /*
8357          * I think this is where he DrvUpgradePrinter() hook would be
8358          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8359          * server.  Right now, we just need to send ourselves a message
8360          * to update each printer bound to this driver.   --jerry
8361          */
8362
8363         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8364                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8365                         fn, driver_name));
8366         }
8367
8368 done:
8369         return err;
8370 }
8371
8372 /****************************************************************
8373  _spoolss_AddPrinterDriver
8374 ****************************************************************/
8375
8376 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8377                                  struct spoolss_AddPrinterDriver *r)
8378 {
8379         struct spoolss_AddPrinterDriverEx a;
8380
8381         switch (r->in.info_ctr->level) {
8382         case 2:
8383         case 3:
8384         case 4:
8385         case 5:
8386                 break;
8387         default:
8388                 return WERR_UNKNOWN_LEVEL;
8389         }
8390
8391         a.in.servername         = r->in.servername;
8392         a.in.info_ctr           = r->in.info_ctr;
8393         a.in.flags              = APD_COPY_NEW_FILES;
8394
8395         return _spoolss_AddPrinterDriverEx(p, &a);
8396 }
8397
8398 /****************************************************************************
8399 ****************************************************************************/
8400
8401 struct _spoolss_paths {
8402         int type;
8403         const char *share;
8404         const char *dir;
8405 };
8406
8407 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8408
8409 static const struct _spoolss_paths spoolss_paths[]= {
8410         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8411         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8412 };
8413
8414 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8415                                           const char *servername,
8416                                           const char *environment,
8417                                           int component,
8418                                           char **path)
8419 {
8420         const char *pservername = NULL;
8421         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8422         const char *short_archi;
8423
8424         *path = NULL;
8425
8426         /* environment may be empty */
8427         if (environment && strlen(environment)) {
8428                 long_archi = environment;
8429         }
8430
8431         /* servername may be empty */
8432         if (servername && strlen(servername)) {
8433                 pservername = canon_servername(servername);
8434
8435                 if (!is_myname_or_ipaddr(pservername)) {
8436                         return WERR_INVALID_PARAM;
8437                 }
8438         }
8439
8440         if (!(short_archi = get_short_archi(long_archi))) {
8441                 return WERR_INVALID_ENVIRONMENT;
8442         }
8443
8444         switch (component) {
8445         case SPOOLSS_PRTPROCS_PATH:
8446         case SPOOLSS_DRIVER_PATH:
8447                 if (pservername) {
8448                         *path = talloc_asprintf(mem_ctx,
8449                                         "\\\\%s\\%s\\%s",
8450                                         pservername,
8451                                         spoolss_paths[component].share,
8452                                         short_archi);
8453                 } else {
8454                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8455                                         SPOOLSS_DEFAULT_SERVER_PATH,
8456                                         spoolss_paths[component].dir,
8457                                         short_archi);
8458                 }
8459                 break;
8460         default:
8461                 return WERR_INVALID_PARAM;
8462         }
8463
8464         if (!*path) {
8465                 return WERR_NOMEM;
8466         }
8467
8468         return WERR_OK;
8469 }
8470
8471 /****************************************************************************
8472 ****************************************************************************/
8473
8474 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8475                                           const char *servername,
8476                                           const char *environment,
8477                                           struct spoolss_DriverDirectoryInfo1 *r)
8478 {
8479         WERROR werr;
8480         char *path = NULL;
8481
8482         werr = compose_spoolss_server_path(mem_ctx,
8483                                            servername,
8484                                            environment,
8485                                            SPOOLSS_DRIVER_PATH,
8486                                            &path);
8487         if (!W_ERROR_IS_OK(werr)) {
8488                 return werr;
8489         }
8490
8491         DEBUG(4,("printer driver directory: [%s]\n", path));
8492
8493         r->directory_name = path;
8494
8495         return WERR_OK;
8496 }
8497
8498 /****************************************************************
8499  _spoolss_GetPrinterDriverDirectory
8500 ****************************************************************/
8501
8502 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8503                                           struct spoolss_GetPrinterDriverDirectory *r)
8504 {
8505         WERROR werror;
8506
8507         /* that's an [in out] buffer */
8508
8509         if (!r->in.buffer && (r->in.offered != 0)) {
8510                 return WERR_INVALID_PARAM;
8511         }
8512
8513         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8514                 r->in.level));
8515
8516         *r->out.needed = 0;
8517
8518         /* r->in.level is ignored */
8519
8520         werror = getprinterdriverdir_level_1(p->mem_ctx,
8521                                              r->in.server,
8522                                              r->in.environment,
8523                                              &r->out.info->info1);
8524         if (!W_ERROR_IS_OK(werror)) {
8525                 TALLOC_FREE(r->out.info);
8526                 return werror;
8527         }
8528
8529         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8530                                                r->out.info, r->in.level);
8531         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8532
8533         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8534 }
8535
8536 /****************************************************************
8537  _spoolss_EnumPrinterData
8538 ****************************************************************/
8539
8540 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8541                                 struct spoolss_EnumPrinterData *r)
8542 {
8543         WERROR result;
8544         struct spoolss_EnumPrinterDataEx r2;
8545         uint32_t count;
8546         struct spoolss_PrinterEnumValues *info, *val = NULL;
8547         uint32_t needed;
8548
8549         r2.in.handle    = r->in.handle;
8550         r2.in.key_name  = "PrinterDriverData";
8551         r2.in.offered   = 0;
8552         r2.out.count    = &count;
8553         r2.out.info     = &info;
8554         r2.out.needed   = &needed;
8555
8556         result = _spoolss_EnumPrinterDataEx(p, &r2);
8557         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8558                 r2.in.offered = needed;
8559                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8560         }
8561         if (!W_ERROR_IS_OK(result)) {
8562                 return result;
8563         }
8564
8565         /*
8566          * The NT machine wants to know the biggest size of value and data
8567          *
8568          * cf: MSDN EnumPrinterData remark section
8569          */
8570
8571         if (!r->in.value_offered && !r->in.data_offered) {
8572                 uint32_t biggest_valuesize = 0;
8573                 uint32_t biggest_datasize = 0;
8574                 int i, name_length;
8575
8576                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8577
8578                 for (i=0; i<count; i++) {
8579
8580                         name_length = strlen(info[i].value_name);
8581                         if (strlen(info[i].value_name) > biggest_valuesize) {
8582                                 biggest_valuesize = name_length;
8583                         }
8584
8585                         if (info[i].data_length > biggest_datasize) {
8586                                 biggest_datasize = info[i].data_length;
8587                         }
8588
8589                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8590                                 biggest_datasize));
8591                 }
8592
8593                 /* the value is an UNICODE string but real_value_size is the length
8594                    in bytes including the trailing 0 */
8595
8596                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8597                 *r->out.data_needed  = biggest_datasize;
8598
8599                 DEBUG(6,("final values: [%d], [%d]\n",
8600                         *r->out.value_needed, *r->out.data_needed));
8601
8602                 return WERR_OK;
8603         }
8604
8605         if (r->in.enum_index < count) {
8606                 val = &info[r->in.enum_index];
8607         }
8608
8609         if (val == NULL) {
8610                 /* out_value should default to "" or else NT4 has
8611                    problems unmarshalling the response */
8612
8613                 if (r->in.value_offered) {
8614                         *r->out.value_needed = 1;
8615                         r->out.value_name = talloc_strdup(r, "");
8616                         if (!r->out.value_name) {
8617                                 return WERR_NOMEM;
8618                         }
8619                 } else {
8620                         r->out.value_name = NULL;
8621                         *r->out.value_needed = 0;
8622                 }
8623
8624                 /* the data is counted in bytes */
8625
8626                 *r->out.data_needed = r->in.data_offered;
8627
8628                 result = WERR_NO_MORE_ITEMS;
8629         } else {
8630                 /*
8631                  * the value is:
8632                  * - counted in bytes in the request
8633                  * - counted in UNICODE chars in the max reply
8634                  * - counted in bytes in the real size
8635                  *
8636                  * take a pause *before* coding not *during* coding
8637                  */
8638
8639                 /* name */
8640                 if (r->in.value_offered) {
8641                         r->out.value_name = talloc_strdup(r, val->value_name);
8642                         if (!r->out.value_name) {
8643                                 return WERR_NOMEM;
8644                         }
8645                         *r->out.value_needed = val->value_name_len;
8646                 } else {
8647                         r->out.value_name = NULL;
8648                         *r->out.value_needed = 0;
8649                 }
8650
8651                 /* type */
8652
8653                 *r->out.type = val->type;
8654
8655                 /* data - counted in bytes */
8656
8657                 /*
8658                  * See the section "Dynamically Typed Query Parameters"
8659                  * in MS-RPRN.
8660                  */
8661
8662                 if (r->out.data && val->data && val->data->data &&
8663                                 val->data_length && r->in.data_offered) {
8664                         memcpy(r->out.data, val->data->data,
8665                                 MIN(val->data_length,r->in.data_offered));
8666                 }
8667
8668                 *r->out.data_needed = val->data_length;
8669
8670                 result = WERR_OK;
8671         }
8672
8673         return result;
8674 }
8675
8676 /****************************************************************
8677  _spoolss_SetPrinterData
8678 ****************************************************************/
8679
8680 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8681                                struct spoolss_SetPrinterData *r)
8682 {
8683         struct spoolss_SetPrinterDataEx r2;
8684
8685         r2.in.handle            = r->in.handle;
8686         r2.in.key_name          = "PrinterDriverData";
8687         r2.in.value_name        = r->in.value_name;
8688         r2.in.type              = r->in.type;
8689         r2.in.data              = r->in.data;
8690         r2.in.offered           = r->in.offered;
8691
8692         return _spoolss_SetPrinterDataEx(p, &r2);
8693 }
8694
8695 /****************************************************************
8696  _spoolss_ResetPrinter
8697 ****************************************************************/
8698
8699 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8700                              struct spoolss_ResetPrinter *r)
8701 {
8702         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8703         int             snum;
8704
8705         DEBUG(5,("_spoolss_ResetPrinter\n"));
8706
8707         /*
8708          * All we do is to check to see if the handle and queue is valid.
8709          * This call really doesn't mean anything to us because we only
8710          * support RAW printing.   --jerry
8711          */
8712
8713         if (!Printer) {
8714                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8715                         OUR_HANDLE(r->in.handle)));
8716                 return WERR_BADFID;
8717         }
8718
8719         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8720                 return WERR_BADFID;
8721
8722
8723         /* blindly return success */
8724         return WERR_OK;
8725 }
8726
8727 /****************************************************************
8728  _spoolss_DeletePrinterData
8729 ****************************************************************/
8730
8731 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8732                                   struct spoolss_DeletePrinterData *r)
8733 {
8734         struct spoolss_DeletePrinterDataEx r2;
8735
8736         r2.in.handle            = r->in.handle;
8737         r2.in.key_name          = "PrinterDriverData";
8738         r2.in.value_name        = r->in.value_name;
8739
8740         return _spoolss_DeletePrinterDataEx(p, &r2);
8741 }
8742
8743 /****************************************************************
8744  _spoolss_AddForm
8745 ****************************************************************/
8746
8747 WERROR _spoolss_AddForm(struct pipes_struct *p,
8748                         struct spoolss_AddForm *r)
8749 {
8750         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8751         int snum = -1;
8752         WERROR status = WERR_OK;
8753         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8754         struct dcerpc_binding_handle *b;
8755         TALLOC_CTX *tmp_ctx = NULL;
8756
8757         DEBUG(5,("_spoolss_AddForm\n"));
8758
8759         if (!Printer) {
8760                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8761                         OUR_HANDLE(r->in.handle)));
8762                 return WERR_BADFID;
8763         }
8764
8765         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8766            and not a printer admin, then fail */
8767
8768         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8769             !security_token_has_privilege(p->session_info->security_token,
8770                                           SEC_PRIV_PRINT_OPERATOR)) {
8771                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8772                 return WERR_ACCESS_DENIED;
8773         }
8774
8775         switch (form->flags) {
8776         case SPOOLSS_FORM_USER:
8777         case SPOOLSS_FORM_BUILTIN:
8778         case SPOOLSS_FORM_PRINTER:
8779                 break;
8780         default:
8781                 return WERR_INVALID_PARAM;
8782         }
8783
8784         tmp_ctx = talloc_new(p->mem_ctx);
8785         if (!tmp_ctx) {
8786                 return WERR_NOMEM;
8787         }
8788
8789         status = winreg_printer_binding_handle(tmp_ctx,
8790                                                get_session_info_system(),
8791                                                p->msg_ctx,
8792                                                &b);
8793         if (!W_ERROR_IS_OK(status)) {
8794                 goto done;
8795         }
8796
8797         status = winreg_printer_addform1(tmp_ctx, b, form);
8798         if (!W_ERROR_IS_OK(status)) {
8799                 goto done;
8800         }
8801
8802         /*
8803          * ChangeID must always be set if this is a printer
8804          */
8805         if (Printer->printer_type == SPLHND_PRINTER) {
8806                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8807                         status = WERR_BADFID;
8808                         goto done;
8809                 }
8810
8811                 status = winreg_printer_update_changeid(tmp_ctx, b,
8812                                                         lp_const_servicename(snum));
8813         }
8814
8815 done:
8816         talloc_free(tmp_ctx);
8817         return status;
8818 }
8819
8820 /****************************************************************
8821  _spoolss_DeleteForm
8822 ****************************************************************/
8823
8824 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8825                            struct spoolss_DeleteForm *r)
8826 {
8827         const char *form_name = r->in.form_name;
8828         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8829         int snum = -1;
8830         WERROR status = WERR_OK;
8831         struct dcerpc_binding_handle *b;
8832         TALLOC_CTX *tmp_ctx = NULL;
8833
8834         DEBUG(5,("_spoolss_DeleteForm\n"));
8835
8836         if (!Printer) {
8837                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8838                         OUR_HANDLE(r->in.handle)));
8839                 return WERR_BADFID;
8840         }
8841
8842         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8843             !security_token_has_privilege(p->session_info->security_token,
8844                                           SEC_PRIV_PRINT_OPERATOR)) {
8845                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8846                 return WERR_ACCESS_DENIED;
8847         }
8848
8849         tmp_ctx = talloc_new(p->mem_ctx);
8850         if (!tmp_ctx) {
8851                 return WERR_NOMEM;
8852         }
8853
8854         status = winreg_printer_binding_handle(tmp_ctx,
8855                                                get_session_info_system(),
8856                                                p->msg_ctx,
8857                                                &b);
8858         if (!W_ERROR_IS_OK(status)) {
8859                 goto done;
8860         }
8861
8862         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8863         if (!W_ERROR_IS_OK(status)) {
8864                 goto done;
8865         }
8866
8867         /*
8868          * ChangeID must always be set if this is a printer
8869          */
8870         if (Printer->printer_type == SPLHND_PRINTER) {
8871                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8872                         status = WERR_BADFID;
8873                         goto done;
8874                 }
8875
8876                 status = winreg_printer_update_changeid(tmp_ctx, b,
8877                                                         lp_const_servicename(snum));
8878         }
8879
8880 done:
8881         talloc_free(tmp_ctx);
8882         return status;
8883 }
8884
8885 /****************************************************************
8886  _spoolss_SetForm
8887 ****************************************************************/
8888
8889 WERROR _spoolss_SetForm(struct pipes_struct *p,
8890                         struct spoolss_SetForm *r)
8891 {
8892         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8893         const char *form_name = r->in.form_name;
8894         int snum = -1;
8895         WERROR status = WERR_OK;
8896         struct dcerpc_binding_handle *b;
8897         TALLOC_CTX *tmp_ctx = NULL;
8898
8899         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8900
8901         DEBUG(5,("_spoolss_SetForm\n"));
8902
8903         if (!Printer) {
8904                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8905                         OUR_HANDLE(r->in.handle)));
8906                 return WERR_BADFID;
8907         }
8908
8909         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8910            and not a printer admin, then fail */
8911
8912         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8913              !security_token_has_privilege(p->session_info->security_token,
8914                                            SEC_PRIV_PRINT_OPERATOR)) {
8915                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8916                 return WERR_ACCESS_DENIED;
8917         }
8918
8919         tmp_ctx = talloc_new(p->mem_ctx);
8920         if (!tmp_ctx) {
8921                 return WERR_NOMEM;
8922         }
8923
8924         status = winreg_printer_binding_handle(tmp_ctx,
8925                                                get_session_info_system(),
8926                                                p->msg_ctx,
8927                                                &b);
8928         if (!W_ERROR_IS_OK(status)) {
8929                 goto done;
8930         }
8931
8932         status = winreg_printer_setform1(tmp_ctx, b,
8933                                          form_name,
8934                                          form);
8935         if (!W_ERROR_IS_OK(status)) {
8936                 goto done;
8937         }
8938
8939         /*
8940          * ChangeID must always be set if this is a printer
8941          */
8942         if (Printer->printer_type == SPLHND_PRINTER) {
8943                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8944                         status = WERR_BADFID;
8945                         goto done;
8946                 }
8947
8948                 status = winreg_printer_update_changeid(tmp_ctx, b,
8949                                                         lp_const_servicename(snum));
8950         }
8951
8952 done:
8953         talloc_free(tmp_ctx);
8954         return status;
8955 }
8956
8957 /****************************************************************************
8958  fill_print_processor1
8959 ****************************************************************************/
8960
8961 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8962                                     struct spoolss_PrintProcessorInfo1 *r,
8963                                     const char *print_processor_name)
8964 {
8965         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8966         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8967
8968         return WERR_OK;
8969 }
8970
8971 /****************************************************************************
8972  enumprintprocessors level 1.
8973 ****************************************************************************/
8974
8975 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8976                                           union spoolss_PrintProcessorInfo **info_p,
8977                                           uint32_t *count)
8978 {
8979         union spoolss_PrintProcessorInfo *info;
8980         WERROR result;
8981
8982         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8983         W_ERROR_HAVE_NO_MEMORY(info);
8984
8985         *count = 1;
8986
8987         result = fill_print_processor1(info, &info[0].info1, "winprint");
8988         if (!W_ERROR_IS_OK(result)) {
8989                 goto out;
8990         }
8991
8992  out:
8993         if (!W_ERROR_IS_OK(result)) {
8994                 TALLOC_FREE(info);
8995                 *count = 0;
8996                 return result;
8997         }
8998
8999         *info_p = info;
9000
9001         return WERR_OK;
9002 }
9003
9004 /****************************************************************
9005  _spoolss_EnumPrintProcessors
9006 ****************************************************************/
9007
9008 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9009                                     struct spoolss_EnumPrintProcessors *r)
9010 {
9011         WERROR result;
9012
9013         /* that's an [in out] buffer */
9014
9015         if (!r->in.buffer && (r->in.offered != 0)) {
9016                 return WERR_INVALID_PARAM;
9017         }
9018
9019         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9020
9021         /*
9022          * Enumerate the print processors ...
9023          *
9024          * Just reply with "winprint", to keep NT happy
9025          * and I can use my nice printer checker.
9026          */
9027
9028         *r->out.count = 0;
9029         *r->out.needed = 0;
9030         *r->out.info = NULL;
9031
9032         if (!get_short_archi(r->in.environment)) {
9033                 return WERR_INVALID_ENVIRONMENT;
9034         }
9035
9036         switch (r->in.level) {
9037         case 1:
9038                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9039                                                      r->out.count);
9040                 break;
9041         default:
9042                 return WERR_UNKNOWN_LEVEL;
9043         }
9044
9045         if (!W_ERROR_IS_OK(result)) {
9046                 return result;
9047         }
9048
9049         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9050                                                      spoolss_EnumPrintProcessors,
9051                                                      *r->out.info, r->in.level,
9052                                                      *r->out.count);
9053         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9054         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9055
9056         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9057 }
9058
9059 /****************************************************************************
9060  fill_printprocdatatype1
9061 ****************************************************************************/
9062
9063 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9064                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9065                                       const char *name_array)
9066 {
9067         r->name_array = talloc_strdup(mem_ctx, name_array);
9068         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9069
9070         return WERR_OK;
9071 }
9072
9073 /****************************************************************************
9074  enumprintprocdatatypes level 1.
9075 ****************************************************************************/
9076
9077 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9078                                              union spoolss_PrintProcDataTypesInfo **info_p,
9079                                              uint32_t *count)
9080 {
9081         WERROR result;
9082         union spoolss_PrintProcDataTypesInfo *info;
9083
9084         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9085         W_ERROR_HAVE_NO_MEMORY(info);
9086
9087         *count = 1;
9088
9089         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9090         if (!W_ERROR_IS_OK(result)) {
9091                 goto out;
9092         }
9093
9094  out:
9095         if (!W_ERROR_IS_OK(result)) {
9096                 TALLOC_FREE(info);
9097                 *count = 0;
9098                 return result;
9099         }
9100
9101         *info_p = info;
9102
9103         return WERR_OK;
9104 }
9105
9106 /****************************************************************
9107  _spoolss_EnumPrintProcDataTypes
9108 ****************************************************************/
9109
9110 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9111                                        struct spoolss_EnumPrintProcDataTypes *r)
9112 {
9113         WERROR result;
9114
9115         /* that's an [in out] buffer */
9116
9117         if (!r->in.buffer && (r->in.offered != 0)) {
9118                 return WERR_INVALID_PARAM;
9119         }
9120
9121         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9122
9123         *r->out.count = 0;
9124         *r->out.needed = 0;
9125         *r->out.info = NULL;
9126
9127         if (r->in.print_processor_name == NULL ||
9128             !strequal(r->in.print_processor_name, "winprint")) {
9129                 return WERR_UNKNOWN_PRINTPROCESSOR;
9130         }
9131
9132         switch (r->in.level) {
9133         case 1:
9134                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9135                                                         r->out.count);
9136                 break;
9137         default:
9138                 return WERR_UNKNOWN_LEVEL;
9139         }
9140
9141         if (!W_ERROR_IS_OK(result)) {
9142                 return result;
9143         }
9144
9145         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9146                                                      spoolss_EnumPrintProcDataTypes,
9147                                                      *r->out.info, r->in.level,
9148                                                      *r->out.count);
9149         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9150         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9151
9152         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9153 }
9154
9155 /****************************************************************************
9156  fill_monitor_1
9157 ****************************************************************************/
9158
9159 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9160                              struct spoolss_MonitorInfo1 *r,
9161                              const char *monitor_name)
9162 {
9163         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9164         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9165
9166         return WERR_OK;
9167 }
9168
9169 /****************************************************************************
9170  fill_monitor_2
9171 ****************************************************************************/
9172
9173 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9174                              struct spoolss_MonitorInfo2 *r,
9175                              const char *monitor_name,
9176                              const char *environment,
9177                              const char *dll_name)
9178 {
9179         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9180         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9181         r->environment                  = talloc_strdup(mem_ctx, environment);
9182         W_ERROR_HAVE_NO_MEMORY(r->environment);
9183         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9184         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9185
9186         return WERR_OK;
9187 }
9188
9189 /****************************************************************************
9190  enumprintmonitors level 1.
9191 ****************************************************************************/
9192
9193 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9194                                         union spoolss_MonitorInfo **info_p,
9195                                         uint32_t *count)
9196 {
9197         union spoolss_MonitorInfo *info;
9198         WERROR result = WERR_OK;
9199
9200         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9201         W_ERROR_HAVE_NO_MEMORY(info);
9202
9203         *count = 2;
9204
9205         result = fill_monitor_1(info, &info[0].info1,
9206                                 SPL_LOCAL_PORT);
9207         if (!W_ERROR_IS_OK(result)) {
9208                 goto out;
9209         }
9210
9211         result = fill_monitor_1(info, &info[1].info1,
9212                                 SPL_TCPIP_PORT);
9213         if (!W_ERROR_IS_OK(result)) {
9214                 goto out;
9215         }
9216
9217 out:
9218         if (!W_ERROR_IS_OK(result)) {
9219                 TALLOC_FREE(info);
9220                 *count = 0;
9221                 return result;
9222         }
9223
9224         *info_p = info;
9225
9226         return WERR_OK;
9227 }
9228
9229 /****************************************************************************
9230  enumprintmonitors level 2.
9231 ****************************************************************************/
9232
9233 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9234                                         union spoolss_MonitorInfo **info_p,
9235                                         uint32_t *count)
9236 {
9237         union spoolss_MonitorInfo *info;
9238         WERROR result = WERR_OK;
9239
9240         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9241         W_ERROR_HAVE_NO_MEMORY(info);
9242
9243         *count = 2;
9244
9245         result = fill_monitor_2(info, &info[0].info2,
9246                                 SPL_LOCAL_PORT,
9247                                 "Windows NT X86", /* FIXME */
9248                                 "localmon.dll");
9249         if (!W_ERROR_IS_OK(result)) {
9250                 goto out;
9251         }
9252
9253         result = fill_monitor_2(info, &info[1].info2,
9254                                 SPL_TCPIP_PORT,
9255                                 "Windows NT X86", /* FIXME */
9256                                 "tcpmon.dll");
9257         if (!W_ERROR_IS_OK(result)) {
9258                 goto out;
9259         }
9260
9261 out:
9262         if (!W_ERROR_IS_OK(result)) {
9263                 TALLOC_FREE(info);
9264                 *count = 0;
9265                 return result;
9266         }
9267
9268         *info_p = info;
9269
9270         return WERR_OK;
9271 }
9272
9273 /****************************************************************
9274  _spoolss_EnumMonitors
9275 ****************************************************************/
9276
9277 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9278                              struct spoolss_EnumMonitors *r)
9279 {
9280         WERROR result;
9281
9282         /* that's an [in out] buffer */
9283
9284         if (!r->in.buffer && (r->in.offered != 0)) {
9285                 return WERR_INVALID_PARAM;
9286         }
9287
9288         DEBUG(5,("_spoolss_EnumMonitors\n"));
9289
9290         /*
9291          * Enumerate the print monitors ...
9292          *
9293          * Just reply with "Local Port", to keep NT happy
9294          * and I can use my nice printer checker.
9295          */
9296
9297         *r->out.count = 0;
9298         *r->out.needed = 0;
9299         *r->out.info = NULL;
9300
9301         switch (r->in.level) {
9302         case 1:
9303                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9304                                                    r->out.count);
9305                 break;
9306         case 2:
9307                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9308                                                    r->out.count);
9309                 break;
9310         default:
9311                 return WERR_UNKNOWN_LEVEL;
9312         }
9313
9314         if (!W_ERROR_IS_OK(result)) {
9315                 return result;
9316         }
9317
9318         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9319                                                      spoolss_EnumMonitors,
9320                                                      *r->out.info, r->in.level,
9321                                                      *r->out.count);
9322         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9323         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9324
9325         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9326 }
9327
9328 /****************************************************************************
9329 ****************************************************************************/
9330
9331 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9332                              const print_queue_struct *queue,
9333                              int count, int snum,
9334                              struct spoolss_PrinterInfo2 *pinfo2,
9335                              uint32_t jobid,
9336                              int sysjob,
9337                              struct spoolss_JobInfo1 *r)
9338 {
9339         int i = 0;
9340         bool found = false;
9341
9342         for (i=0; i<count; i++) {
9343                 if (queue[i].sysjob == sysjob) {
9344                         found = true;
9345                         break;
9346                 }
9347         }
9348
9349         if (found == false) {
9350                 /* NT treats not found as bad param... yet another bad choice */
9351                 return WERR_INVALID_PARAM;
9352         }
9353
9354         return fill_job_info1(mem_ctx,
9355                               r,
9356                               &queue[i],
9357                               jobid,
9358                               i,
9359                               snum,
9360                               pinfo2);
9361 }
9362
9363 /****************************************************************************
9364 ****************************************************************************/
9365
9366 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9367                              const print_queue_struct *queue,
9368                              int count, int snum,
9369                              struct spoolss_PrinterInfo2 *pinfo2,
9370                              uint32_t jobid,
9371                              int sysjob,
9372                              struct spoolss_JobInfo2 *r)
9373 {
9374         int i = 0;
9375         bool found = false;
9376         struct spoolss_DeviceMode *devmode;
9377         WERROR result;
9378
9379         for (i=0; i<count; i++) {
9380                 if (queue[i].sysjob == sysjob) {
9381                         found = true;
9382                         break;
9383                 }
9384         }
9385
9386         if (found == false) {
9387                 /* NT treats not found as bad param... yet another bad
9388                    choice */
9389                 return WERR_INVALID_PARAM;
9390         }
9391
9392         /*
9393          * if the print job does not have a DEVMODE associated with it,
9394          * just use the one for the printer. A NULL devicemode is not
9395          *  a failure condition
9396          */
9397
9398         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9399         if (!devmode) {
9400                 result = spoolss_create_default_devmode(mem_ctx,
9401                                                 pinfo2->printername,
9402                                                 &devmode);
9403                 if (!W_ERROR_IS_OK(result)) {
9404                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9405                         return result;
9406                 }
9407         }
9408
9409         return fill_job_info2(mem_ctx,
9410                               r,
9411                               &queue[i],
9412                               i,
9413                               snum,
9414                               pinfo2,
9415                               devmode);
9416 }
9417
9418 /****************************************************************
9419  _spoolss_GetJob
9420 ****************************************************************/
9421
9422 WERROR _spoolss_GetJob(struct pipes_struct *p,
9423                        struct spoolss_GetJob *r)
9424 {
9425         WERROR result = WERR_OK;
9426         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9427         const char *svc_name;
9428         int sysjob;
9429         int snum;
9430         int count;
9431         struct tdb_print_db *pdb;
9432         print_queue_struct      *queue = NULL;
9433         print_status_struct prt_status;
9434
9435         /* that's an [in out] buffer */
9436
9437         if (!r->in.buffer && (r->in.offered != 0)) {
9438                 return WERR_INVALID_PARAM;
9439         }
9440
9441         DEBUG(5,("_spoolss_GetJob\n"));
9442
9443         *r->out.needed = 0;
9444
9445         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9446                 return WERR_BADFID;
9447         }
9448
9449         svc_name = lp_const_servicename(snum);
9450         if (svc_name == NULL) {
9451                 return WERR_INVALID_PARAM;
9452         }
9453
9454         result = winreg_get_printer_internal(p->mem_ctx,
9455                                     get_session_info_system(),
9456                                     p->msg_ctx,
9457                                     svc_name,
9458                                     &pinfo2);
9459         if (!W_ERROR_IS_OK(result)) {
9460                 return result;
9461         }
9462
9463         pdb = get_print_db_byname(svc_name);
9464         if (pdb == NULL) {
9465                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9466                 TALLOC_FREE(pinfo2);
9467                 return WERR_INVALID_PARAM;
9468         }
9469
9470         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9471         release_print_db(pdb);
9472         if (sysjob == -1) {
9473                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9474                 TALLOC_FREE(pinfo2);
9475                 return WERR_INVALID_PARAM;
9476         }
9477
9478         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9479
9480         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9481                      count, prt_status.status, prt_status.message));
9482
9483         switch (r->in.level) {
9484         case 1:
9485                 result = getjob_level_1(p->mem_ctx,
9486                                         queue, count, snum, pinfo2,
9487                                         r->in.job_id, sysjob,
9488                                         &r->out.info->info1);
9489                 break;
9490         case 2:
9491                 result = getjob_level_2(p->mem_ctx,
9492                                         queue, count, snum, pinfo2,
9493                                         r->in.job_id, sysjob,
9494                                         &r->out.info->info2);
9495                 break;
9496         default:
9497                 result = WERR_UNKNOWN_LEVEL;
9498                 break;
9499         }
9500
9501         SAFE_FREE(queue);
9502         TALLOC_FREE(pinfo2);
9503
9504         if (!W_ERROR_IS_OK(result)) {
9505                 TALLOC_FREE(r->out.info);
9506                 return result;
9507         }
9508
9509         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9510                                                                                    r->in.level);
9511         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9512
9513         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9514 }
9515
9516 /****************************************************************
9517  _spoolss_GetPrinterDataEx
9518 ****************************************************************/
9519
9520 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9521                                  struct spoolss_GetPrinterDataEx *r)
9522 {
9523
9524         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9525         const char *printer;
9526         int                     snum = 0;
9527         WERROR result = WERR_OK;
9528         DATA_BLOB blob;
9529         enum winreg_Type val_type = REG_NONE;
9530         uint8_t *val_data = NULL;
9531         uint32_t val_size = 0;
9532         struct dcerpc_binding_handle *b;
9533         TALLOC_CTX *tmp_ctx;
9534
9535         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9536
9537         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9538                 r->in.key_name, r->in.value_name));
9539
9540         /* in case of problem, return some default values */
9541
9542         *r->out.needed  = 0;
9543         *r->out.type    = REG_NONE;
9544
9545         tmp_ctx = talloc_new(p->mem_ctx);
9546         if (!tmp_ctx) {
9547                 return WERR_NOMEM;
9548         }
9549
9550         if (!Printer) {
9551                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9552                         OUR_HANDLE(r->in.handle)));
9553                 result = WERR_BADFID;
9554                 goto done;
9555         }
9556
9557         /* check to see if the keyname is valid */
9558         if (!strlen(r->in.key_name)) {
9559                 result = WERR_INVALID_PARAM;
9560                 goto done;
9561         }
9562
9563         /* Is the handle to a printer or to the server? */
9564
9565         if (Printer->printer_type == SPLHND_SERVER) {
9566
9567                 union spoolss_PrinterData data;
9568
9569                 result = getprinterdata_printer_server(tmp_ctx,
9570                                                        r->in.value_name,
9571                                                        r->out.type,
9572                                                        &data);
9573                 if (!W_ERROR_IS_OK(result)) {
9574                         goto done;
9575                 }
9576
9577                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9578                                                   *r->out.type, &data);
9579                 if (!W_ERROR_IS_OK(result)) {
9580                         goto done;
9581                 }
9582
9583                 *r->out.needed = blob.length;
9584
9585                 if (r->in.offered >= *r->out.needed) {
9586                         memcpy(r->out.data, blob.data, blob.length);
9587                 }
9588
9589                 result = WERR_OK;
9590                 goto done;
9591         }
9592
9593         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9594                 result = WERR_BADFID;
9595                 goto done;
9596         }
9597         printer = lp_const_servicename(snum);
9598
9599         result = winreg_printer_binding_handle(tmp_ctx,
9600                                                get_session_info_system(),
9601                                                p->msg_ctx,
9602                                                &b);
9603         if (!W_ERROR_IS_OK(result)) {
9604                 goto done;
9605         }
9606
9607         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9608         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9609             strequal(r->in.value_name, "ChangeId")) {
9610                 *r->out.type = REG_DWORD;
9611                 *r->out.needed = 4;
9612                 if (r->in.offered >= *r->out.needed) {
9613                         uint32_t changeid = 0;
9614
9615                         result = winreg_printer_get_changeid(tmp_ctx, b,
9616                                                              printer,
9617                                                              &changeid);
9618                         if (!W_ERROR_IS_OK(result)) {
9619                                 goto done;
9620                         }
9621
9622                         SIVAL(r->out.data, 0, changeid);
9623                         result = WERR_OK;
9624                 }
9625                 goto done;
9626         }
9627
9628         result = winreg_get_printer_dataex(tmp_ctx, b,
9629                                            printer,
9630                                            r->in.key_name,
9631                                            r->in.value_name,
9632                                            &val_type,
9633                                            &val_data,
9634                                            &val_size);
9635         if (!W_ERROR_IS_OK(result)) {
9636                 goto done;
9637         }
9638
9639         *r->out.needed = val_size;
9640         *r->out.type = val_type;
9641
9642         if (r->in.offered >= *r->out.needed) {
9643                 memcpy(r->out.data, val_data, val_size);
9644         }
9645
9646 done:
9647         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9648
9649         if (W_ERROR_IS_OK(result)) {
9650                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9651         }
9652
9653         talloc_free(tmp_ctx);
9654         return result;
9655 }
9656
9657 /****************************************************************
9658  _spoolss_SetPrinterDataEx
9659 ****************************************************************/
9660
9661 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9662                                  struct spoolss_SetPrinterDataEx *r)
9663 {
9664         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9665         int                     snum = 0;
9666         WERROR                  result = WERR_OK;
9667         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9668         char                    *oid_string;
9669         struct dcerpc_binding_handle *b;
9670         TALLOC_CTX *tmp_ctx;
9671
9672         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9673
9674         /* From MSDN documentation of SetPrinterDataEx: pass request to
9675            SetPrinterData if key is "PrinterDriverData" */
9676
9677         if (!Printer) {
9678                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9679                         OUR_HANDLE(r->in.handle)));
9680                 return WERR_BADFID;
9681         }
9682
9683         if (Printer->printer_type == SPLHND_SERVER) {
9684                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9685                         "Not implemented for server handles yet\n"));
9686                 return WERR_INVALID_PARAM;
9687         }
9688
9689         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9690                 return WERR_BADFID;
9691         }
9692
9693         /*
9694          * Access check : NT returns "access denied" if you make a
9695          * SetPrinterData call without the necessary privildge.
9696          * we were originally returning OK if nothing changed
9697          * which made Win2k issue **a lot** of SetPrinterData
9698          * when connecting to a printer  --jerry
9699          */
9700
9701         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9702                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9703                         "change denied by handle access permissions\n"));
9704                 return WERR_ACCESS_DENIED;
9705         }
9706
9707         tmp_ctx = talloc_new(p->mem_ctx);
9708         if (!tmp_ctx) {
9709                 return WERR_NOMEM;
9710         }
9711
9712         result = winreg_printer_binding_handle(tmp_ctx,
9713                                                get_session_info_system(),
9714                                                p->msg_ctx,
9715                                                &b);
9716         if (!W_ERROR_IS_OK(result)) {
9717                 goto done;
9718         }
9719
9720         result = winreg_get_printer(tmp_ctx, b,
9721                                     lp_servicename(talloc_tos(), snum),
9722                                     &pinfo2);
9723         if (!W_ERROR_IS_OK(result)) {
9724                 goto done;
9725         }
9726
9727         /* check for OID in valuename */
9728
9729         oid_string = strchr(r->in.value_name, ',');
9730         if (oid_string) {
9731                 *oid_string = '\0';
9732                 oid_string++;
9733         }
9734
9735         /* save the registry data */
9736
9737         result = winreg_set_printer_dataex(tmp_ctx, b,
9738                                            pinfo2->sharename,
9739                                            r->in.key_name,
9740                                            r->in.value_name,
9741                                            r->in.type,
9742                                            r->in.data,
9743                                            r->in.offered);
9744
9745         if (W_ERROR_IS_OK(result)) {
9746                 /* save the OID if one was specified */
9747                 if (oid_string) {
9748                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9749                                 r->in.key_name, SPOOL_OID_KEY);
9750                         if (!str) {
9751                                 result = WERR_NOMEM;
9752                                 goto done;
9753                         }
9754
9755                         /*
9756                          * I'm not checking the status here on purpose.  Don't know
9757                          * if this is right, but I'm returning the status from the
9758                          * previous set_printer_dataex() call.  I have no idea if
9759                          * this is right.    --jerry
9760                          */
9761                         winreg_set_printer_dataex(tmp_ctx, b,
9762                                                   pinfo2->sharename,
9763                                                   str,
9764                                                   r->in.value_name,
9765                                                   REG_SZ,
9766                                                   (uint8_t *) oid_string,
9767                                                   strlen(oid_string) + 1);
9768                 }
9769
9770                 result = winreg_printer_update_changeid(tmp_ctx, b,
9771                                                         lp_const_servicename(snum));
9772
9773         }
9774
9775 done:
9776         talloc_free(tmp_ctx);
9777         return result;
9778 }
9779
9780 /****************************************************************
9781  _spoolss_DeletePrinterDataEx
9782 ****************************************************************/
9783
9784 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9785                                     struct spoolss_DeletePrinterDataEx *r)
9786 {
9787         const char *printer;
9788         int             snum=0;
9789         WERROR          status = WERR_OK;
9790         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9791
9792         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9793
9794         if (!Printer) {
9795                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9796                         "Invalid handle (%s:%u:%u).\n",
9797                         OUR_HANDLE(r->in.handle)));
9798                 return WERR_BADFID;
9799         }
9800
9801         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9802                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9803                         "printer properties change denied by handle\n"));
9804                 return WERR_ACCESS_DENIED;
9805         }
9806
9807         if (!r->in.value_name || !r->in.key_name) {
9808                 return WERR_NOMEM;
9809         }
9810
9811         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9812                 return WERR_BADFID;
9813         }
9814         printer = lp_const_servicename(snum);
9815
9816         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9817                                               get_session_info_system(),
9818                                               p->msg_ctx,
9819                                               printer,
9820                                               r->in.key_name,
9821                                               r->in.value_name);
9822         if (W_ERROR_IS_OK(status)) {
9823                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9824                                                         get_session_info_system(),
9825                                                         p->msg_ctx,
9826                                                         printer);
9827         }
9828
9829         return status;
9830 }
9831
9832 /****************************************************************
9833  _spoolss_EnumPrinterKey
9834 ****************************************************************/
9835
9836 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9837                                struct spoolss_EnumPrinterKey *r)
9838 {
9839         uint32_t        num_keys;
9840         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9841         int             snum = 0;
9842         WERROR          result = WERR_BADFILE;
9843         const char **array = NULL;
9844         DATA_BLOB blob;
9845
9846         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9847
9848         if (!Printer) {
9849                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9850                         OUR_HANDLE(r->in.handle)));
9851                 return WERR_BADFID;
9852         }
9853
9854         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9855                 return WERR_BADFID;
9856         }
9857
9858         result = winreg_enum_printer_key_internal(p->mem_ctx,
9859                                          get_session_info_system(),
9860                                          p->msg_ctx,
9861                                          lp_const_servicename(snum),
9862                                          r->in.key_name,
9863                                          &num_keys,
9864                                          &array);
9865         if (!W_ERROR_IS_OK(result)) {
9866                 goto done;
9867         }
9868
9869         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9870                 result = WERR_NOMEM;
9871                 goto done;
9872         }
9873
9874         *r->out._ndr_size = r->in.offered / 2;
9875         *r->out.needed = blob.length;
9876
9877         if (r->in.offered < *r->out.needed) {
9878                 result = WERR_MORE_DATA;
9879         } else {
9880                 result = WERR_OK;
9881                 r->out.key_buffer->string_array = array;
9882         }
9883
9884  done:
9885         if (!W_ERROR_IS_OK(result)) {
9886                 TALLOC_FREE(array);
9887                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9888                         *r->out.needed = 0;
9889                 }
9890         }
9891
9892         return result;
9893 }
9894
9895 /****************************************************************
9896  _spoolss_DeletePrinterKey
9897 ****************************************************************/
9898
9899 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9900                                  struct spoolss_DeletePrinterKey *r)
9901 {
9902         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9903         int                     snum=0;
9904         WERROR                  status;
9905         const char *printer;
9906         struct dcerpc_binding_handle *b;
9907         TALLOC_CTX *tmp_ctx;
9908
9909         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9910
9911         if (!Printer) {
9912                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9913                         OUR_HANDLE(r->in.handle)));
9914                 return WERR_BADFID;
9915         }
9916
9917         /* if keyname == NULL, return error */
9918         if ( !r->in.key_name )
9919                 return WERR_INVALID_PARAM;
9920
9921         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9922                 return WERR_BADFID;
9923         }
9924
9925         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9926                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9927                         "printer properties change denied by handle\n"));
9928                 return WERR_ACCESS_DENIED;
9929         }
9930
9931         printer = lp_const_servicename(snum);
9932
9933         tmp_ctx = talloc_new(p->mem_ctx);
9934         if (!tmp_ctx) {
9935                 return WERR_NOMEM;
9936         }
9937
9938         status = winreg_printer_binding_handle(tmp_ctx,
9939                                                get_session_info_system(),
9940                                                p->msg_ctx,
9941                                                &b);
9942         if (!W_ERROR_IS_OK(status)) {
9943                 goto done;
9944         }
9945
9946         /* delete the key and all subkeys */
9947         status = winreg_delete_printer_key(tmp_ctx, b,
9948                                            printer,
9949                                            r->in.key_name);
9950         if (W_ERROR_IS_OK(status)) {
9951                 status = winreg_printer_update_changeid(tmp_ctx, b,
9952                                                         printer);
9953         }
9954
9955 done:
9956         talloc_free(tmp_ctx);
9957         return status;
9958 }
9959
9960 /****************************************************************
9961  _spoolss_EnumPrinterDataEx
9962 ****************************************************************/
9963
9964 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9965                                   struct spoolss_EnumPrinterDataEx *r)
9966 {
9967         uint32_t        count = 0;
9968         struct spoolss_PrinterEnumValues *info = NULL;
9969         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9970         int             snum;
9971         WERROR          result;
9972
9973         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9974
9975         *r->out.count = 0;
9976         *r->out.needed = 0;
9977         *r->out.info = NULL;
9978
9979         if (!Printer) {
9980                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9981                         OUR_HANDLE(r->in.handle)));
9982                 return WERR_BADFID;
9983         }
9984
9985         /*
9986          * first check for a keyname of NULL or "".  Win2k seems to send
9987          * this a lot and we should send back WERR_INVALID_PARAM
9988          * no need to spend time looking up the printer in this case.
9989          * --jerry
9990          */
9991
9992         if (!strlen(r->in.key_name)) {
9993                 result = WERR_INVALID_PARAM;
9994                 goto done;
9995         }
9996
9997         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9998                 return WERR_BADFID;
9999         }
10000
10001         /* now look for a match on the key name */
10002         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10003                                             get_session_info_system(),
10004                                             p->msg_ctx,
10005                                             lp_const_servicename(snum),
10006                                             r->in.key_name,
10007                                             &count,
10008                                             &info);
10009         if (!W_ERROR_IS_OK(result)) {
10010                 goto done;
10011         }
10012
10013 #if 0 /* FIXME - gd */
10014         /* housekeeping information in the reply */
10015
10016         /* Fix from Martin Zielinski <mz@seh.de> - ensure
10017          * the hand marshalled container size is a multiple
10018          * of 4 bytes for RPC alignment.
10019          */
10020
10021         if (needed % 4) {
10022                 needed += 4-(needed % 4);
10023         }
10024 #endif
10025         *r->out.count   = count;
10026         *r->out.info    = info;
10027
10028  done:
10029         if (!W_ERROR_IS_OK(result)) {
10030                 return result;
10031         }
10032
10033         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10034                                                spoolss_EnumPrinterDataEx,
10035                                                *r->out.info,
10036                                                *r->out.count);
10037         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10038         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10039
10040         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10041 }
10042
10043 /****************************************************************************
10044 ****************************************************************************/
10045
10046 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10047                                                  const char *servername,
10048                                                  const char *environment,
10049                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
10050 {
10051         WERROR werr;
10052         char *path = NULL;
10053
10054         werr = compose_spoolss_server_path(mem_ctx,
10055                                            servername,
10056                                            environment,
10057                                            SPOOLSS_PRTPROCS_PATH,
10058                                            &path);
10059         if (!W_ERROR_IS_OK(werr)) {
10060                 return werr;
10061         }
10062
10063         DEBUG(4,("print processor directory: [%s]\n", path));
10064
10065         r->directory_name = path;
10066
10067         return WERR_OK;
10068 }
10069
10070 /****************************************************************
10071  _spoolss_GetPrintProcessorDirectory
10072 ****************************************************************/
10073
10074 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10075                                            struct spoolss_GetPrintProcessorDirectory *r)
10076 {
10077         WERROR result;
10078         char *prnproc_share = NULL;
10079         bool prnproc_share_exists = false;
10080         int snum;
10081
10082         /* that's an [in out] buffer */
10083
10084         if (!r->in.buffer && (r->in.offered != 0)) {
10085                 return WERR_INVALID_PARAM;
10086         }
10087
10088         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10089                 r->in.level));
10090
10091         *r->out.needed = 0;
10092
10093         /* r->in.level is ignored */
10094
10095         /* We always should reply with a local print processor directory so that
10096          * users are not forced to have a [prnproc$] share on the Samba spoolss
10097          * server, if users decide to do so, lets announce it though - Guenther */
10098
10099         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10100         if (!prnproc_share) {
10101                 return WERR_NOMEM;
10102         }
10103         if (snum != -1) {
10104                 prnproc_share_exists = true;
10105         }
10106
10107         result = getprintprocessordirectory_level_1(p->mem_ctx,
10108                                                     prnproc_share_exists ? r->in.server : NULL,
10109                                                     r->in.environment,
10110                                                     &r->out.info->info1);
10111         if (!W_ERROR_IS_OK(result)) {
10112                 TALLOC_FREE(r->out.info);
10113                 return result;
10114         }
10115
10116         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10117                                                                                    r->out.info, r->in.level);
10118         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10119
10120         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10121 }
10122
10123 /*******************************************************************
10124  ********************************************************************/
10125
10126 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10127                                const char *dllname)
10128 {
10129         enum ndr_err_code ndr_err;
10130         struct spoolss_MonitorUi ui;
10131
10132         ui.dll_name = dllname;
10133
10134         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10135                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10136         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10137                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10138         }
10139         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10140 }
10141
10142 /*******************************************************************
10143  Streams the monitor UI DLL name in UNICODE
10144 *******************************************************************/
10145
10146 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10147                                struct security_token *token, DATA_BLOB *in,
10148                                DATA_BLOB *out, uint32_t *needed)
10149 {
10150         const char *dllname = "tcpmonui.dll";
10151
10152         *needed = (strlen(dllname)+1) * 2;
10153
10154         if (out->length < *needed) {
10155                 return WERR_INSUFFICIENT_BUFFER;
10156         }
10157
10158         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10159                 return WERR_NOMEM;
10160         }
10161
10162         return WERR_OK;
10163 }
10164
10165 /*******************************************************************
10166  ********************************************************************/
10167
10168 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10169                              struct spoolss_PortData1 *port1,
10170                              const DATA_BLOB *buf)
10171 {
10172         enum ndr_err_code ndr_err;
10173         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10174                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10175         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10176                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10177         }
10178         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10179 }
10180
10181 /*******************************************************************
10182  ********************************************************************/
10183
10184 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10185                              struct spoolss_PortData2 *port2,
10186                              const DATA_BLOB *buf)
10187 {
10188         enum ndr_err_code ndr_err;
10189         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10190                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10191         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10192                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10193         }
10194         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10195 }
10196
10197 /*******************************************************************
10198  Create a new TCP/IP port
10199 *******************************************************************/
10200
10201 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10202                              struct security_token *token, DATA_BLOB *in,
10203                              DATA_BLOB *out, uint32_t *needed)
10204 {
10205         struct spoolss_PortData1 port1;
10206         struct spoolss_PortData2 port2;
10207         char *device_uri = NULL;
10208         uint32_t version;
10209
10210         const char *portname;
10211         const char *hostaddress;
10212         const char *queue;
10213         uint32_t port_number;
10214         uint32_t protocol;
10215
10216         /* peek for spoolss_PortData version */
10217
10218         if (!in || (in->length < (128 + 4))) {
10219                 return WERR_GENERAL_FAILURE;
10220         }
10221
10222         version = IVAL(in->data, 128);
10223
10224         switch (version) {
10225                 case 1:
10226                         ZERO_STRUCT(port1);
10227
10228                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10229                                 return WERR_NOMEM;
10230                         }
10231
10232                         portname        = port1.portname;
10233                         hostaddress     = port1.hostaddress;
10234                         queue           = port1.queue;
10235                         protocol        = port1.protocol;
10236                         port_number     = port1.port_number;
10237
10238                         break;
10239                 case 2:
10240                         ZERO_STRUCT(port2);
10241
10242                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10243                                 return WERR_NOMEM;
10244                         }
10245
10246                         portname        = port2.portname;
10247                         hostaddress     = port2.hostaddress;
10248                         queue           = port2.queue;
10249                         protocol        = port2.protocol;
10250                         port_number     = port2.port_number;
10251
10252                         break;
10253                 default:
10254                         DEBUG(1,("xcvtcp_addport: "
10255                                 "unknown version of port_data: %d\n", version));
10256                         return WERR_UNKNOWN_PORT;
10257         }
10258
10259         /* create the device URI and call the add_port_hook() */
10260
10261         switch (protocol) {
10262         case PROTOCOL_RAWTCP_TYPE:
10263                 device_uri = talloc_asprintf(mem_ctx,
10264                                 "socket://%s:%d/", hostaddress,
10265                                 port_number);
10266                 break;
10267
10268         case PROTOCOL_LPR_TYPE:
10269                 device_uri = talloc_asprintf(mem_ctx,
10270                         "lpr://%s/%s", hostaddress, queue );
10271                 break;
10272
10273         default:
10274                 return WERR_UNKNOWN_PORT;
10275         }
10276
10277         if (!device_uri) {
10278                 return WERR_NOMEM;
10279         }
10280
10281         return add_port_hook(mem_ctx, token, portname, device_uri);
10282 }
10283
10284 /*******************************************************************
10285 *******************************************************************/
10286
10287 struct xcv_api_table xcvtcp_cmds[] = {
10288         { "MonitorUI",  xcvtcp_monitorui },
10289         { "AddPort",    xcvtcp_addport},
10290         { NULL,         NULL }
10291 };
10292
10293 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10294                                      struct security_token *token, const char *command,
10295                                      DATA_BLOB *inbuf,
10296                                      DATA_BLOB *outbuf,
10297                                      uint32_t *needed )
10298 {
10299         int i;
10300
10301         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10302
10303         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10304                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10305                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10306         }
10307
10308         return WERR_BADFUNC;
10309 }
10310
10311 /*******************************************************************
10312 *******************************************************************/
10313 #if 0   /* don't support management using the "Local Port" monitor */
10314
10315 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10316                                  struct security_token *token, DATA_BLOB *in,
10317                                  DATA_BLOB *out, uint32_t *needed)
10318 {
10319         const char *dllname = "localui.dll";
10320
10321         *needed = (strlen(dllname)+1) * 2;
10322
10323         if (out->length < *needed) {
10324                 return WERR_INSUFFICIENT_BUFFER;
10325         }
10326
10327         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10328                 return WERR_NOMEM;
10329         }
10330
10331         return WERR_OK;
10332 }
10333
10334 /*******************************************************************
10335 *******************************************************************/
10336
10337 struct xcv_api_table xcvlocal_cmds[] = {
10338         { "MonitorUI",  xcvlocal_monitorui },
10339         { NULL,         NULL }
10340 };
10341 #else
10342 struct xcv_api_table xcvlocal_cmds[] = {
10343         { NULL,         NULL }
10344 };
10345 #endif
10346
10347
10348
10349 /*******************************************************************
10350 *******************************************************************/
10351
10352 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10353                                        struct security_token *token, const char *command,
10354                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10355                                        uint32_t *needed)
10356 {
10357         int i;
10358
10359         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10360
10361         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10362                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10363                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10364         }
10365         return WERR_BADFUNC;
10366 }
10367
10368 /****************************************************************
10369  _spoolss_XcvData
10370 ****************************************************************/
10371
10372 WERROR _spoolss_XcvData(struct pipes_struct *p,
10373                         struct spoolss_XcvData *r)
10374 {
10375         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10376         DATA_BLOB out_data = data_blob_null;
10377         WERROR werror;
10378
10379         if (!Printer) {
10380                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10381                         OUR_HANDLE(r->in.handle)));
10382                 return WERR_BADFID;
10383         }
10384
10385         /* Has to be a handle to the TCP/IP port monitor */
10386
10387         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10388                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10389                 return WERR_BADFID;
10390         }
10391
10392         /* requires administrative access to the server */
10393
10394         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10395                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10396                 return WERR_ACCESS_DENIED;
10397         }
10398
10399         /* Allocate the outgoing buffer */
10400
10401         if (r->in.out_data_size) {
10402                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10403                 if (out_data.data == NULL) {
10404                         return WERR_NOMEM;
10405                 }
10406         }
10407
10408         switch ( Printer->printer_type ) {
10409         case SPLHND_PORTMON_TCP:
10410                 werror = process_xcvtcp_command(p->mem_ctx,
10411                                                 p->session_info->security_token,
10412                                                 r->in.function_name,
10413                                                 &r->in.in_data, &out_data,
10414                                                 r->out.needed);
10415                 break;
10416         case SPLHND_PORTMON_LOCAL:
10417                 werror = process_xcvlocal_command(p->mem_ctx,
10418                                                   p->session_info->security_token,
10419                                                   r->in.function_name,
10420                                                   &r->in.in_data, &out_data,
10421                                                   r->out.needed);
10422                 break;
10423         default:
10424                 werror = WERR_INVALID_PRINT_MONITOR;
10425         }
10426
10427         if (!W_ERROR_IS_OK(werror)) {
10428                 return werror;
10429         }
10430
10431         *r->out.status_code = 0;
10432
10433         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10434                 memcpy(r->out.out_data, out_data.data,
10435                         MIN(r->in.out_data_size, out_data.length));
10436         }
10437
10438         return WERR_OK;
10439 }
10440
10441 /****************************************************************
10442  _spoolss_AddPrintProcessor
10443 ****************************************************************/
10444
10445 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10446                                   struct spoolss_AddPrintProcessor *r)
10447 {
10448         /* for now, just indicate success and ignore the add.  We'll
10449            automatically set the winprint processor for printer
10450            entries later.  Used to debug the LexMark Optra S 1855 PCL
10451            driver --jerry */
10452
10453         return WERR_OK;
10454 }
10455
10456 /****************************************************************
10457  _spoolss_AddPort
10458 ****************************************************************/
10459
10460 WERROR _spoolss_AddPort(struct pipes_struct *p,
10461                         struct spoolss_AddPort *r)
10462 {
10463         /* do what w2k3 does */
10464
10465         return WERR_NOT_SUPPORTED;
10466 }
10467
10468 /****************************************************************
10469  _spoolss_GetPrinterDriver
10470 ****************************************************************/
10471
10472 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10473                                  struct spoolss_GetPrinterDriver *r)
10474 {
10475         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10476         return WERR_NOT_SUPPORTED;
10477 }
10478
10479 /****************************************************************
10480  _spoolss_ReadPrinter
10481 ****************************************************************/
10482
10483 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10484                             struct spoolss_ReadPrinter *r)
10485 {
10486         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10487         return WERR_NOT_SUPPORTED;
10488 }
10489
10490 /****************************************************************
10491  _spoolss_WaitForPrinterChange
10492 ****************************************************************/
10493
10494 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10495                                      struct spoolss_WaitForPrinterChange *r)
10496 {
10497         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10498         return WERR_NOT_SUPPORTED;
10499 }
10500
10501 /****************************************************************
10502  _spoolss_ConfigurePort
10503 ****************************************************************/
10504
10505 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10506                               struct spoolss_ConfigurePort *r)
10507 {
10508         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10509         return WERR_NOT_SUPPORTED;
10510 }
10511
10512 /****************************************************************
10513  _spoolss_DeletePort
10514 ****************************************************************/
10515
10516 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10517                            struct spoolss_DeletePort *r)
10518 {
10519         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10520         return WERR_NOT_SUPPORTED;
10521 }
10522
10523 /****************************************************************
10524  _spoolss_CreatePrinterIC
10525 ****************************************************************/
10526
10527 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10528                                 struct spoolss_CreatePrinterIC *r)
10529 {
10530         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10531         return WERR_NOT_SUPPORTED;
10532 }
10533
10534 /****************************************************************
10535  _spoolss_PlayGDIScriptOnPrinterIC
10536 ****************************************************************/
10537
10538 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10539                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10540 {
10541         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10542         return WERR_NOT_SUPPORTED;
10543 }
10544
10545 /****************************************************************
10546  _spoolss_DeletePrinterIC
10547 ****************************************************************/
10548
10549 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10550                                 struct spoolss_DeletePrinterIC *r)
10551 {
10552         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10553         return WERR_NOT_SUPPORTED;
10554 }
10555
10556 /****************************************************************
10557  _spoolss_AddPrinterConnection
10558 ****************************************************************/
10559
10560 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10561                                      struct spoolss_AddPrinterConnection *r)
10562 {
10563         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10564         return WERR_NOT_SUPPORTED;
10565 }
10566
10567 /****************************************************************
10568  _spoolss_DeletePrinterConnection
10569 ****************************************************************/
10570
10571 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10572                                         struct spoolss_DeletePrinterConnection *r)
10573 {
10574         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10575         return WERR_NOT_SUPPORTED;
10576 }
10577
10578 /****************************************************************
10579  _spoolss_PrinterMessageBox
10580 ****************************************************************/
10581
10582 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10583                                   struct spoolss_PrinterMessageBox *r)
10584 {
10585         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10586         return WERR_NOT_SUPPORTED;
10587 }
10588
10589 /****************************************************************
10590  _spoolss_AddMonitor
10591 ****************************************************************/
10592
10593 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10594                            struct spoolss_AddMonitor *r)
10595 {
10596         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10597         return WERR_NOT_SUPPORTED;
10598 }
10599
10600 /****************************************************************
10601  _spoolss_DeleteMonitor
10602 ****************************************************************/
10603
10604 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10605                               struct spoolss_DeleteMonitor *r)
10606 {
10607         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10608         return WERR_NOT_SUPPORTED;
10609 }
10610
10611 /****************************************************************
10612  _spoolss_DeletePrintProcessor
10613 ****************************************************************/
10614
10615 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10616                                      struct spoolss_DeletePrintProcessor *r)
10617 {
10618         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10619         return WERR_NOT_SUPPORTED;
10620 }
10621
10622 /****************************************************************
10623  _spoolss_AddPrintProvidor
10624 ****************************************************************/
10625
10626 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10627                                  struct spoolss_AddPrintProvidor *r)
10628 {
10629         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10630         return WERR_NOT_SUPPORTED;
10631 }
10632
10633 /****************************************************************
10634  _spoolss_DeletePrintProvidor
10635 ****************************************************************/
10636
10637 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10638                                     struct spoolss_DeletePrintProvidor *r)
10639 {
10640         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10641         return WERR_NOT_SUPPORTED;
10642 }
10643
10644 /****************************************************************
10645  _spoolss_FindFirstPrinterChangeNotification
10646 ****************************************************************/
10647
10648 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10649                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10650 {
10651         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10652         return WERR_NOT_SUPPORTED;
10653 }
10654
10655 /****************************************************************
10656  _spoolss_FindNextPrinterChangeNotification
10657 ****************************************************************/
10658
10659 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10660                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10661 {
10662         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10663         return WERR_NOT_SUPPORTED;
10664 }
10665
10666 /****************************************************************
10667  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10668 ****************************************************************/
10669
10670 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10671                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10672 {
10673         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10674         return WERR_NOT_SUPPORTED;
10675 }
10676
10677 /****************************************************************
10678  _spoolss_ReplyOpenPrinter
10679 ****************************************************************/
10680
10681 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10682                                  struct spoolss_ReplyOpenPrinter *r)
10683 {
10684         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10685         return WERR_NOT_SUPPORTED;
10686 }
10687
10688 /****************************************************************
10689  _spoolss_RouterReplyPrinter
10690 ****************************************************************/
10691
10692 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10693                                    struct spoolss_RouterReplyPrinter *r)
10694 {
10695         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10696         return WERR_NOT_SUPPORTED;
10697 }
10698
10699 /****************************************************************
10700  _spoolss_ReplyClosePrinter
10701 ****************************************************************/
10702
10703 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10704                                   struct spoolss_ReplyClosePrinter *r)
10705 {
10706         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10707         return WERR_NOT_SUPPORTED;
10708 }
10709
10710 /****************************************************************
10711  _spoolss_AddPortEx
10712 ****************************************************************/
10713
10714 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10715                           struct spoolss_AddPortEx *r)
10716 {
10717         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10718         return WERR_NOT_SUPPORTED;
10719 }
10720
10721 /****************************************************************
10722  _spoolss_RouterFindFirstPrinterChangeNotification
10723 ****************************************************************/
10724
10725 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10726                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10727 {
10728         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10729         return WERR_NOT_SUPPORTED;
10730 }
10731
10732 /****************************************************************
10733  _spoolss_SpoolerInit
10734 ****************************************************************/
10735
10736 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10737                             struct spoolss_SpoolerInit *r)
10738 {
10739         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10740         return WERR_NOT_SUPPORTED;
10741 }
10742
10743 /****************************************************************
10744  _spoolss_ResetPrinterEx
10745 ****************************************************************/
10746
10747 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10748                                struct spoolss_ResetPrinterEx *r)
10749 {
10750         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10751         return WERR_NOT_SUPPORTED;
10752 }
10753
10754 /****************************************************************
10755  _spoolss_RouterReplyPrinterEx
10756 ****************************************************************/
10757
10758 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10759                                      struct spoolss_RouterReplyPrinterEx *r)
10760 {
10761         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10762         return WERR_NOT_SUPPORTED;
10763 }
10764
10765 /****************************************************************
10766  _spoolss_44
10767 ****************************************************************/
10768
10769 WERROR _spoolss_44(struct pipes_struct *p,
10770                    struct spoolss_44 *r)
10771 {
10772         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10773         return WERR_NOT_SUPPORTED;
10774 }
10775
10776 /****************************************************************
10777  _spoolss_SetPort
10778 ****************************************************************/
10779
10780 WERROR _spoolss_SetPort(struct pipes_struct *p,
10781                         struct spoolss_SetPort *r)
10782 {
10783         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10784         return WERR_NOT_SUPPORTED;
10785 }
10786
10787 /****************************************************************
10788  _spoolss_4a
10789 ****************************************************************/
10790
10791 WERROR _spoolss_4a(struct pipes_struct *p,
10792                    struct spoolss_4a *r)
10793 {
10794         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10795         return WERR_NOT_SUPPORTED;
10796 }
10797
10798 /****************************************************************
10799  _spoolss_4b
10800 ****************************************************************/
10801
10802 WERROR _spoolss_4b(struct pipes_struct *p,
10803                    struct spoolss_4b *r)
10804 {
10805         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10806         return WERR_NOT_SUPPORTED;
10807 }
10808
10809 /****************************************************************
10810  _spoolss_4c
10811 ****************************************************************/
10812
10813 WERROR _spoolss_4c(struct pipes_struct *p,
10814                    struct spoolss_4c *r)
10815 {
10816         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10817         return WERR_NOT_SUPPORTED;
10818 }
10819
10820 /****************************************************************
10821  _spoolss_53
10822 ****************************************************************/
10823
10824 WERROR _spoolss_53(struct pipes_struct *p,
10825                    struct spoolss_53 *r)
10826 {
10827         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10828         return WERR_NOT_SUPPORTED;
10829 }
10830
10831 /****************************************************************
10832  _spoolss_AddPerMachineConnection
10833 ****************************************************************/
10834
10835 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10836                                         struct spoolss_AddPerMachineConnection *r)
10837 {
10838         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10839         return WERR_NOT_SUPPORTED;
10840 }
10841
10842 /****************************************************************
10843  _spoolss_DeletePerMachineConnection
10844 ****************************************************************/
10845
10846 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10847                                            struct spoolss_DeletePerMachineConnection *r)
10848 {
10849         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10850         return WERR_NOT_SUPPORTED;
10851 }
10852
10853 /****************************************************************
10854  _spoolss_EnumPerMachineConnections
10855 ****************************************************************/
10856
10857 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10858                                           struct spoolss_EnumPerMachineConnections *r)
10859 {
10860         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10861         return WERR_NOT_SUPPORTED;
10862 }
10863
10864 /****************************************************************
10865  _spoolss_5a
10866 ****************************************************************/
10867
10868 WERROR _spoolss_5a(struct pipes_struct *p,
10869                    struct spoolss_5a *r)
10870 {
10871         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10872         return WERR_NOT_SUPPORTED;
10873 }
10874
10875 /****************************************************************
10876  _spoolss_5b
10877 ****************************************************************/
10878
10879 WERROR _spoolss_5b(struct pipes_struct *p,
10880                    struct spoolss_5b *r)
10881 {
10882         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10883         return WERR_NOT_SUPPORTED;
10884 }
10885
10886 /****************************************************************
10887  _spoolss_5c
10888 ****************************************************************/
10889
10890 WERROR _spoolss_5c(struct pipes_struct *p,
10891                    struct spoolss_5c *r)
10892 {
10893         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10894         return WERR_NOT_SUPPORTED;
10895 }
10896
10897 /****************************************************************
10898  _spoolss_5d
10899 ****************************************************************/
10900
10901 WERROR _spoolss_5d(struct pipes_struct *p,
10902                    struct spoolss_5d *r)
10903 {
10904         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10905         return WERR_NOT_SUPPORTED;
10906 }
10907
10908 /****************************************************************
10909  _spoolss_5e
10910 ****************************************************************/
10911
10912 WERROR _spoolss_5e(struct pipes_struct *p,
10913                    struct spoolss_5e *r)
10914 {
10915         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10916         return WERR_NOT_SUPPORTED;
10917 }
10918
10919 /****************************************************************
10920  _spoolss_5f
10921 ****************************************************************/
10922
10923 WERROR _spoolss_5f(struct pipes_struct *p,
10924                    struct spoolss_5f *r)
10925 {
10926         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10927         return WERR_NOT_SUPPORTED;
10928 }
10929
10930 /****************************************************************
10931  _spoolss_60
10932 ****************************************************************/
10933
10934 WERROR _spoolss_60(struct pipes_struct *p,
10935                    struct spoolss_60 *r)
10936 {
10937         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10938         return WERR_NOT_SUPPORTED;
10939 }
10940
10941 /****************************************************************
10942  _spoolss_61
10943 ****************************************************************/
10944
10945 WERROR _spoolss_61(struct pipes_struct *p,
10946                    struct spoolss_61 *r)
10947 {
10948         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10949         return WERR_NOT_SUPPORTED;
10950 }
10951
10952 /****************************************************************
10953  _spoolss_62
10954 ****************************************************************/
10955
10956 WERROR _spoolss_62(struct pipes_struct *p,
10957                    struct spoolss_62 *r)
10958 {
10959         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10960         return WERR_NOT_SUPPORTED;
10961 }
10962
10963 /****************************************************************
10964  _spoolss_63
10965 ****************************************************************/
10966
10967 WERROR _spoolss_63(struct pipes_struct *p,
10968                    struct spoolss_63 *r)
10969 {
10970         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10971         return WERR_NOT_SUPPORTED;
10972 }
10973
10974 /****************************************************************
10975  _spoolss_64
10976 ****************************************************************/
10977
10978 WERROR _spoolss_64(struct pipes_struct *p,
10979                    struct spoolss_64 *r)
10980 {
10981         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10982         return WERR_NOT_SUPPORTED;
10983 }
10984
10985 /****************************************************************
10986  _spoolss_65
10987 ****************************************************************/
10988
10989 WERROR _spoolss_65(struct pipes_struct *p,
10990                    struct spoolss_65 *r)
10991 {
10992         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10993         return WERR_NOT_SUPPORTED;
10994 }
10995
10996 /****************************************************************
10997  _spoolss_GetCorePrinterDrivers
10998 ****************************************************************/
10999
11000 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11001                                       struct spoolss_GetCorePrinterDrivers *r)
11002 {
11003         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11004         return WERR_NOT_SUPPORTED;
11005 }
11006
11007 /****************************************************************
11008  _spoolss_67
11009 ****************************************************************/
11010
11011 WERROR _spoolss_67(struct pipes_struct *p,
11012                    struct spoolss_67 *r)
11013 {
11014         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11015         return WERR_NOT_SUPPORTED;
11016 }
11017
11018 /****************************************************************
11019  _spoolss_GetPrinterDriverPackagePath
11020 ****************************************************************/
11021
11022 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11023                                             struct spoolss_GetPrinterDriverPackagePath *r)
11024 {
11025         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11026         return WERR_NOT_SUPPORTED;
11027 }
11028
11029 /****************************************************************
11030  _spoolss_69
11031 ****************************************************************/
11032
11033 WERROR _spoolss_69(struct pipes_struct *p,
11034                    struct spoolss_69 *r)
11035 {
11036         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11037         return WERR_NOT_SUPPORTED;
11038 }
11039
11040 /****************************************************************
11041  _spoolss_6a
11042 ****************************************************************/
11043
11044 WERROR _spoolss_6a(struct pipes_struct *p,
11045                    struct spoolss_6a *r)
11046 {
11047         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11048         return WERR_NOT_SUPPORTED;
11049 }
11050
11051 /****************************************************************
11052  _spoolss_6b
11053 ****************************************************************/
11054
11055 WERROR _spoolss_6b(struct pipes_struct *p,
11056                    struct spoolss_6b *r)
11057 {
11058         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11059         return WERR_NOT_SUPPORTED;
11060 }
11061
11062 /****************************************************************
11063  _spoolss_6c
11064 ****************************************************************/
11065
11066 WERROR _spoolss_6c(struct pipes_struct *p,
11067                    struct spoolss_6c *r)
11068 {
11069         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11070         return WERR_NOT_SUPPORTED;
11071 }
11072
11073 /****************************************************************
11074  _spoolss_6d
11075 ****************************************************************/
11076
11077 WERROR _spoolss_6d(struct pipes_struct *p,
11078                    struct spoolss_6d *r)
11079 {
11080         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11081         return WERR_NOT_SUPPORTED;
11082 }